【星闪 SLE 学习笔记 09】:配对成功就安全了吗?从配对记录到断线恢复实测

本文是我学习星闪 SLE 的第九篇笔记。前面几篇已经走过广播、连接、SSAP 数据传输、连接参数和 SDK 能力边界,这一篇继续研究一个更接近实际产品的问题:设备配对之后,断电重连是否一定更快、更可靠?
一、这次问题是怎么出现的
在 BearPi-Pico H3863 的 SLE UART 示例中,Client 连接 Server 前会主动删除目标设备的配对记录,断开后也会再次删除,然后重新扫描、连接和配对。
第一次看到这段代码时,我有一个很自然的疑问:既然已经配对,为什么不保留记录,下次直接恢复连接?
于是我设计了三个实验:
结果并不是“保留记录后重连更快”。在当前 SDK 和复位方式下,仅保留 Client 一侧的旧记录会让系统进入“连接—配对失败—断开”的循环。加入陈旧记录清理兜底后,业务可以恢复,但恢复路径反而更长。
这篇文章记录完整过程,也顺便厘清一个容易混淆的问题:看到 pair complete,并不等于我们已经证明了整条业务链路的安全性。
二、先区分几个容易混在一起的概念
1. 连接状态
连接表示两个设备已经建立 SLE ACB 链路。WS63 公开接口将连接状态定义为:
SLE_ACB_STATE_NONE = 0x00
SLE_ACB_STATE_CONNECTED = 0x01
SLE_ACB_STATE_DISCONNECTED = 0x02
它回答的是“链路是否建立”,不直接回答“对端是否可信”以及“某个 SSAP 属性是否要求加密访问”。
2. 配对状态
连接回调同时会报告配对状态:
SLE_PAIR_NONE = 0x01
SLE_PAIR_PAIRING = 0x02
SLE_PAIR_PAIRED = 0x03
在本次日志中,pair_state_on_connect=1 对应 SLE_PAIR_NONE,表示连接建立时协议栈报告尚未配对。海思 WS63 Connection API
3. 配对完成回调与认证完成回调
sle_connection_callbacks_t 中同时存在:
sle_auth_complete_callback auth_complete_cb;
sle_pair_complete_callback pair_complete_cb;
这说明在 SDK 接口层面,“认证完成”和“配对完成”至少是两个独立的可观察事件。本文实验记录了连接状态和配对完成状态,但没有仅凭 pair complete status=0 就宣称空口上所有数据都已经得到某种确定强度的保护。
4. SSAP 属性权限
SSAP 公开定义中存在以下权限位:
SSAP_PERMISSION_READ
SSAP_PERMISSION_WRITE
SSAP_PERMISSION_ENCRYPTION_NEED
SSAP_PERMISSION_AUTHENTICATION_NEED
SSAP_PERMISSION_AUTHORIZATION_NEED
但当前 UART Server 样例实际配置为:
#define SLE_UUID_TEST_PROPERTIES \\
(SSAP_PERMISSION_READ | SSAP_PERMISSION_WRITE)
也就是说,SDK 提供“需要加密、需要认证、需要授权”等权限位,不代表当前 UART 属性已经启用了这些访问要求。权限枚举可在海思 WS63 SSAP Client API中核对。
因此,更准确的认识是:
连接成功 ≠ 配对成功
配对成功 ≠ 已验证全部业务数据的安全属性
SDK 提供安全权限位 ≠ 当前样例已经启用这些权限位

图:连接状态、配对状态和 SSAP 属性权限分别回答不同问题。
三、UART 示例原本是怎样恢复连接的
本次工程路径为:
application/samples/products/sle_uart/
├── sle_uart.c
├── sle_uart_client/sle_uart_client.c
└── sle_uart_server/sle_uart_server.c
官方 UART 透传流程是:Client 扫描并连接 Server,完成配对、MTU 交换和服务发现;Client 到 Server 使用 Write Request,Server 到 Client 使用 Notification。断开后 Server 恢复广播,Client 恢复扫描。海思 WS63 UART 透传示例
我手中 SDK 的 Client 样例在停止扫描、准备连接时执行:
sle_remove_paired_remote_device(&g_sle_uart_remote_addr);
sle_connect_remote_device(&g_sle_uart_remote_addr);
断开后又执行:
sle_remove_paired_remote_device(&g_sle_uart_remote_addr);
sle_uart_start_scan();
而在连接成功、回调报告 SLE_PAIR_NONE 时,再发起配对:
if (pair_state == SLE_PAIR_NONE) {
sle_pair_remote_device(&g_sle_uart_remote_addr);
}
所以这份示例的默认策略不是“尽可能复用旧配对关系”,而是清理旧记录后重新配对。它适合作为演示流程,但不能直接当作所有产品的配对管理策略。
还有一个很重要的接口细节:官方文档说明 sle_remove_paired_remote_device() 是异步操作。函数返回 ERRCODE_SUCC,只表示删除请求成功发起;最终结果应通过 pair_remove_cb 获取。因此,下文日志中的 remove_local_record_ret=0x0 不能写成“删除完成回调成功”,只能写成“删除请求被接口接受”。海思 WS63 Connection API
四、实验环境与测试方法
1. 实验环境
- 两块 BearPi-Pico H3863;
- 带 2.4 GHz 外置天线的开发板作为 Server,COM4;
- 另一块开发板作为 Client,COM3;
- 串口参数:115200、8N1、无流控;
- Ubuntu 使用官网提供的系统镜像;
- SDK 和软件包来自官方公开资源;
- Server 复位作为断线来源,Client 始终保持运行;
- 所有阶段耗时都由 Client 单端 uapi_tcxo_get_us() 计时,避免两块板时钟不同步。
2. 恢复阶段划分
Client 记录四个阶段:
检测到断开
→ 再次建立可用连接
→ 配对完成
→ MTU交换与服务发现完成
→ 开始完整性测试
这里的“断开到服务就绪”从 Client 收到断开事件开始,不包含我按下 Server 复位键之前的等待时间;它包含 Server 启动、广播、连接、配对和服务发现等多个过程,不能解释成某一个协议步骤的纯时延。
3. 每轮 100 包完整性测试
服务发现完成后,Client 自动发送 100 个 16 字节测试包。测试包中包含固定魔数、递增序号、发送时间戳和固定校验字节。
Client 检查:
- 写请求是否提交成功;
- 写确认是否成功;
- 是否在超时前收到回显;
- 回显序号、时间戳和校验字节是否一致。
Server 检查:
- 接收包数;
- 序号是否连续;
- 固定内容是否正确;
- Notification 回显是否提交成功。
因此,本实验验证的是恢复后的应用层数据路径,不是空口密码学测试。
五、实验 A:重连前主动删除配对记录
实验 A 保持示例的核心策略:连接前和断开后主动删除目标设备的配对记录,然后重新连接、重新配对。
第 1 轮是首次启动,没有断开时间点;第 2~5 轮为 Server 复位后的恢复结果:
| 2 | 137.253 ms | 258.626 ms | 72.510 ms | 468.389 ms |
| 3 | 217.591 ms | 253.218 ms | 72.468 ms | 543.277 ms |
| 4 | 104.604 ms | 253.677 ms | 72.510 ms | 430.791 ms |
| 5 | 64.311 ms | 356.502 ms | 84.938 ms | 505.751 ms |
| 平均 | 130.940 ms | 280.506 ms | 75.606 ms | 487.052 ms |
每次连接时,Client 都报告:
[SECURITY] … pair_state_on_connect=1 mode=remove_pair
[SECURITY] … pair_complete status=0x0
数据结果为:
Client:5/5 轮 PASS
Server:5/5 轮 PASS
总计:500 包
timeout=0
mismatch=0
sequence_error=0
content_error=0
echo_error=0
在本次环境中,主动清理旧记录后重新配对,可以稳定恢复业务。
六、实验 B1:只保留 Client 配对记录
接下来只改一个策略:Client 不再主动调用 sle_remove_paired_remote_device()。
第 1 轮仍然正常,100 包全部通过。Server 复位后,问题出现了:
[Connected]
[SECURITY] cycle=2 pair_state_on_connect=1 mode=retain_pair
[SECURITY] cycle=2 pair_complete status=0x8000600f
[Disconnected]
随后系统不断重复:
扫描
→ 连接成功
→ pair_state=1
→ 配对完成回调返回0x8000600f
→ 断开
→ 再次扫描
Client 没有再次进入 MTU 交换和服务发现,第 2 轮数据测试也无法开始。
两端日志还给出了不同视角的断开原因:
- Client:disc_reason=0x11;
- Server:disc_reason=0x10。
官方枚举中,0x11 表示本端断链,0x10 表示远端断链。两端日志是相互对应的:Client 一侧报告本端断开,Server 一侧看到远端断开。海思 WS63 Connection API
我没有在当前公开头文件和文档中找到 0x8000600f 对应的可核实符号名称,所以这里只把它称为“配对完成回调返回的非零状态码”,不擅自解释具体内部含义。
到这一步只能提出一个假设:Client 保留的旧记录与 Server 复位后的状态不一致,导致重新配对失败。还需要对照实验验证。
七、实验 B2:配对失败后清理陈旧记录
我在 B1 基础上增加一个受控兜底:平时继续保留记录;只有配对回调失败时,才请求删除目标设备的本地配对记录。
if (status == ERRCODE_SUCC) {
/* 继续 MTU 交换 */
} else {
errcode_t remove_ret =
sle_remove_paired_remote_device(&g_sle_uart_remote_addr);
osal_printk("[SECURITY][STALE_PAIR_FALLBACK] "
"pair_status=0x%x remove_local_record_ret=0x%x\\r\\n",
status, remove_ret);
}
实际状态链变成:
Server复位
→ Client检测到断开
→ 第一次重连
→ 配对返回0x8000600f
→ 删除旧记录的请求返回0x0
→ 连接断开
→ 第二次重连
→ 配对返回0x0
→ MTU交换
→ 服务发现完成
→ 100包测试通过

图:B2 中先复现配对失败,再请求清理陈旧记录,第二次连接恢复业务。
第 2~5 轮都复现了相同过程:第一次配对失败,删除请求被接受,下一次连接重新配对成功。
需要再次强调:remove_local_record_ret=0x0 只证明异步删除请求成功发起。本文没有注册 pair_remove_cb,所以不能用它直接证明删除完成;但是,B1 稳定失败、B2 加入该操作后 4/4 次恢复成功,这组行为对照有力支持“旧配对记录参与触发了失败”的判断。
最终恢复时间如下:
| 2 | 260.860 ms | 259.903 ms | 72.489 ms | 593.252 ms |
| 3 | 297.147 ms | 261.171 ms | 72.488 ms | 630.806 ms |
| 4 | 264.539 ms | 268.605 ms | 72.509 ms | 605.653 ms |
| 5 | 287.800 ms | 270.521 ms | 72.458 ms | 630.779 ms |
| 平均 | 277.586 ms | 265.050 ms | 72.486 ms | 615.122 ms |
这里的“第一次断开→最终连接”包含第一次连接、失败配对、清理请求、再次断开和第二次连接,因此不能与实验 A 的“断开→连接”直接视为相同阶段;两组“断开→服务就绪”起止点一致,可以用于本次实验内的端到端对照。
八、三组实验放在一起看
| A | 重连前主动删除 | 4/4 次断线恢复成功 | 5 轮、500 包通过 |
| B1 | 始终保留 | 第 1 轮正常;复位后进入配对失败循环 | 第 2 轮无法开始 |
| B2 | 先保留;失败后清理 | 4/4 次通过兜底恢复 | 5 轮、500 包通过 |
实验 A 与 B2 的端到端恢复时间为:
| A:预先删除配对记录 | 487.052 ms | 4 |
| B2:失败后清理陈旧记录 | 615.122 ms | 4 |

图:B2 多出失败配对和额外连接尝试,因此本次实验中的平均恢复路径更长。
B2 平均多 128.070 ms,约增加 26.3%。这不是芯片规格,也不是可以外推的性能宣传数字,只是本次 4 个恢复样本的观察值。它说明的重点是:失败配对和额外一次连接尝试扩大了恢复路径。
数据完整性方面,A 与 B2 各完成 500 包测试,共计 1000 包,没有观察到测试程序能够识别的超时、错序、内容错误或回显错误。
九、这次实验能证明什么,不能证明什么
可以证明或直接观察到的事实
- 当前 UART 样例会主动调用删除配对记录接口;
- 连接回调报告的 pair_state;
- 配对完成回调的状态值;
- B1 中稳定出现配对失败与重连循环;
- B2 中删除请求返回 0x0 后,下一次连接恢复配对;
- 服务发现是否完成;
- 本次应用层测试包是否出现超时、错序或内容错误;
- 当前 UART 属性只配置了读写权限,没有配置三个安全要求位。
仅凭本实验不能证明的内容
- 所有无线空口数据一定采用了哪一种加密算法;
- pair complete status=0 等价于完整的端到端安全认证;
- SDK 内部密钥如何保存、何时失效以及是否安全持久化;
- 系统能够抵抗重放、中间人、密钥提取等攻击;
- H3863 在其他 SDK、其他断电方式或其他产品配置下也一定表现相同。
如果要继续做真正的安全验证,至少还需要:注册并分析认证与配对删除回调、明确 SSAP 安全权限配置、使用空口分析或官方安全测试手段,并审计密钥生命周期。本文没有打印 link_key 或完整设备地址,避免为了调试把敏感材料写入日志。
十、我从这次实验得到的工程启示
1. 不要把“保留记录”直接等同于“快速重连”
配对记录要想复用,双方状态必须一致。只保留一侧记录,未必能减少步骤,反而可能把系统带入失败循环。
2. 恢复逻辑必须有失败出口
一个更稳妥的状态机应该限制重试次数,并对特定失败阶段提供兜底:
连接
├─ 已满足后续条件 → MTU交换与服务发现
└─ 需要配对
├─ 配对成功 → 继续
└─ 配对失败 → 清理陈旧记录 → 限次重连
如果清理后仍失败,应进入退避或故障状态,而不是无限高频扫描、连接和断开。
3. 异步接口要看完成回调
sle_remove_paired_remote_device() 返回成功不代表删除动作已经完成。正式产品代码应注册 pair_remove_cb,根据完成回调推进状态机,而不是只依赖 API 的同步返回值。
4. 恢复成功不能只看 Connected
本次 B1 中每一次都能看到 Connected,但业务并没有恢复。更合理的“恢复成功”判据应至少包括:
连接建立
+ 配对/认证状态满足要求
+ MTU交换完成
+ 服务发现完成
+ 第一笔业务数据成功
十一、总结
这次实验最值得记录的,不是某个毫秒数字,而是一个很具体的工程事实:连接成功只是恢复链路的开始,配对记录是否一致会直接影响后续配对和业务恢复。
在当前 BearPi-Pico H3863、官方 SDK UART 样例和 Server 复位条件下:
- 预先清理配对记录后重新配对,能够稳定恢复;
- 只保留 Client 旧记录,会出现配对失败和重复重连;
- 配对失败后请求清理旧记录,可以让下一次连接重新配对并恢复业务;
- 恢复后的 1000 个测试包未观察到应用层完整性错误;
- pair complete 日志本身不能替代对认证、权限、空口保护和密钥管理的验证。
对我来说,这一篇把“配对”从一个成功日志变成了一个需要管理生命周期、异常状态和恢复策略的工程对象。下一篇将把前九篇内容收束到一个完整项目中,综合使用广播、连接、SSAP、参数配置、可靠性统计和异常恢复。
参考资料
说明:本文中的时间和成功率均来自本次两块开发板的小样本实验,只用于描述当前实验现象,不代表官方规格或通用性能结论。





