安全子系统详解¶
本文详细解释 SparkLink SLE 安全子系统的设计与实现, 涵盖配对鉴权、密钥派生、帧加密、隐私保护和 UWB 测量安全, 对标 TXS-10002-2025 标准第 9 章。
安全架构¶
SLE 安全子系统分为三层:
配对鉴权层: 建立信任关系, 交换密钥材料 (§9.2)
帧加密层: 保护数据传输的机密性和完整性 (§9.3)
隐私保护层: 防止设备追踪 (§9.4)
安全的基础是 ECDH P-256 密钥协商, 派生出所有后续密钥。
配对流程 (§9.2)¶
配对是两个设备首次建立安全关联的过程。标准定义了 6 种鉴权方法:
方法 |
适用场景 |
|---|---|
数值比较 |
双方有显示和输入能力 |
密码输入 |
一方有输入能力 |
密码校验 |
预共享密码 |
带外传输 |
NFC 等侧信道 |
预共享密钥 |
工厂预置密钥 |
无输入 |
无交互能力 (Just Works) |
鉴权方法的选择由双方 IO 能力 (无输入无输出、仅显示、仅键盘、显示+键盘、显示+是否) 协商决定。
配对状态机¶
配对流程由 9 个状态组成:
stateDiagram-v2
[*] --> IDLE
IDLE --> INITIATED
INITIATED --> REQUEST_SENT
REQUEST_SENT --> RESPONSE_SENT
RESPONSE_SENT --> CONFIRM_SENT
CONFIRM_SENT --> PUBLIC_KEY_EXCHANGED
PUBLIC_KEY_EXCHANGED --> CONFIRM_CODE_SENT
CONFIRM_CODE_SENT --> COMPLETED
CONFIRM_CODE_SENT --> FAILED
COMPLETED --> [*]
FAILED --> [*]
G 节点视角:
IDLE → REQUEST_SENT: 发送
PairingRequest, 携带 IO 能力、密钥长度、安全分发信息、加密能力REQUEST_SENT → CONFIRM_SENT: 收到
PairingResponse, 发送PairingConfirm(含 G 节点 P-256 公钥 X/Y 坐标, 各 32 字节)CONFIRM_SENT → PUBLIC_KEY_EXCHANGED: 收到
PairingInitialInfo(T 节点公钥), 计算 ECDH 共享密钥, 发送 Ra 随机数PUBLIC_KEY_EXCHANGED → CONFIRM_CODE_SENT: 收到 Rb, 发送
GNodeConfirmCodeCONFIRM_CODE_SENT → COMPLETED: 收到
TNodeConfirmCode, 验证确认码, 派生密钥
T 节点视角是上述流程的镜像:
IDLE → INITIATED: 收到
PairingInitiateINITIATED → RESPONSE_SENT: 收到
PairingRequest, 发送PairingResponseRESPONSE_SENT → PUBLIC_KEY_EXCHANGED: 收到
PairingConfirm, 保存 G 公钥, 发送自身公钥PUBLIC_KEY_EXCHANGED → CONFIRM_CODE_SENT: 收到 Ra, 计算 DH Key, 发送 Rb
CONFIRM_CODE_SENT → COMPLETED: 收到
GNodeConfirmCode, 验证后发送TNodeConfirmCode, 派生密钥
失败处理¶
12 种失败原因:
代码 |
原因 |
|---|---|
0x01 |
密码输入失败 |
0x02 |
带外数据不可用 |
0x03 |
鉴权要求不满足 |
0x04 |
确认值校验失败 |
0x05 |
配对不支持 |
0x06 |
密钥长度不足 |
0x07 |
命令不支持 |
0x08 |
未指定原因 |
0x09 |
重复尝试 |
0x0A |
参数无效 |
0x0B |
DH Key 校验失败 |
0x0C |
数值比较失败 |
代码实现: mac.security_manager.PairingManager 实现状态机, mac.security 模块定义 20 种配对信令消息类, mac.security_manager.ECDHKeyPair 封装 P-256 椭圆曲线运算。
密钥派生 (§9.3)¶
配对完成后, 通过 ECDH 共享密钥逐级派生出各功能密钥:
flowchart TD
DH["ECDH P-256 共享密钥 (32 字节)"]
DH --> LK["Link Key (16 字节)\nKDF(dh_key_low128, 'lk' ‖ Ra ‖ Rb ‖ 地址)"]
DH --> DK["DH Verify Key\nKDF(dh_key_low128, 'dk' ‖ Ra ‖ Rb ‖ 地址)"]
DK --> DV["DH 验证码 (16 字节)"]
DH --> SK["Session Key (16 字节)\nKDF(link_key, G_Diversifier ‖ T_Diversifier)"]
SK --> AE["认证加密: SK 同时用于加密和完整性"]
SK --> SEP["分离算法: EnK (加密) + InK (完整性)"]
KDF 算法¶
标准支持两种 KDF:
AES-CMAC: 128 位密钥, 输出 128 位 MAC (§9.3.4)
HMAC-SM3: 256 位摘要取低 128 位 (§9.3.4)
双方在配对阶段协商使用哪种 KDF。
确认码生成 (§9.3.4.3)¶
确认码保证远端设备确实持有 DH Key。生成方式取决于鉴权方法:
数值比较: KDF(PKax, PKax ‖ PKbx ‖ Ra ‖ 0)
密码输入: KDF(PKax, PKax ‖ PKbx ‖ Ra ‖ Ri)
密码校验: KDF(PKax, PKax ‖ PKbx ‖ Ra ‖ Pwd)
带外/预共享/Just Works: 类似数值比较
数值比较码 (§9.3.4.6)¶
从 KDF 输出取 4 字节, 对 \(10^6\) 取模, 得到 6 位十进制数字, 双方显示给用户比对。
代码实现: mac.crypto 模块实现全部密钥派生函数:
aes_cmac(),hmac_sm3(),kdf()derive_link_key(),derive_session_key(),derive_dh_verify_key()generate_confirm_code(),generate_dh_verify_code(),generate_numeric_code()obfuscate()混淆算法 (§9.3.4.7)secure_random_256()安全随机函数 (§6.10.7)
帧加密 (§9.3.1)¶
AES-CCM¶
SLE 使用 AES-CCM (Counter with CBC-MAC) 进行帧加密, 同时保证机密性和完整性:
机密性: AES-CTR 模式加密载荷
完整性: CBC-MAC 生成 MIC (消息完整性校验码), 长度 4/8/12/16 字节
Nonce 构建¶
Nonce 是 AES-CCM 的关键输入, 保证每个帧使用不同的计数器:
异步/同步单播和组播链路:
┌───────┬──────────────────┬────────────┬─────────────┬──────────┐
│ Flag │ payload_count │ Direction │ IV │ data_len │
│ 1B │ 5B (bit38:0) │ 1b │ 8B │ 2B │
└───────┴──────────────────┴────────────┴─────────────┴──────────┘
payload_count: 单调递增计数器 (39 位), 防止 nonce 重用Direction: 0 = G→T, 1 = T→GIV: 由 IV 基值和帧参数计算得出
其他链路 (广播/SMF):
┌───────┬──────────────────┬────────────┬─────────────┬──────────┐
│ Flag │ slot_seq │ day_count │ IV │ data_len │
│ 1B │ 4B (bit29:0) │ 2B(bit9:0) │ 8B │ 2B │
└───────┴──────────────────┴────────────┴─────────────┴──────────┘
IV 计算 (§9.3.1)¶
IV 基值 (8 字节) 与不同参数异或:
FT1/FT2: IV = IV_base \(\oplus\) 同步序列号
FT3/FT4: IV = IV_base \(\oplus\) 链路 ID
代码实现: mac.security_manager.FrameCryptoContext 管理加解密上下文, 维护 TX/RX payload_count, 调用 mac.crypto.aes_ccm_encrypt()/aes_ccm_decrypt()。
组播安全 (§9.3.2)¶
组播链路使用独立的密钥体系:
RAND1, RAND2 (各 16 字节随机数)
│
└─► 组播密钥 GK = KDF(RAND1, RAND2)
│
└─► 组播会话密钥 GSK (16B)
或 GEnK + GInK (各 16B)
分发流程:
G 节点生成 RAND 和 KDF/加密/完整性算法参数, 通过
MulticastAlgorithmConfig发送G 节点计算 \(K_g\) = KDF(link_key, RAND), 发送 \(C\) = \(K_g \oplus GK\) 通过
MulticastKeyConfigT 节点用自身 link_key 计算 \(K_g\), 恢复 \(GK\) = \(C \oplus K_g\)
代码实现: mac.crypto.generate_group_key(), derive_group_session_key(), derive_kg(); mac.security 模块定义 MulticastAlgorithmConfig 和 MulticastKeyConfig 信令。
隐私保护 (§9.4)¶
SLE 支持可解析随机地址, 防止第三方追踪设备:
设备生成 IRK (身份解析密钥, 16 字节), 在配对阶段通过
GNodeIRK/TNodeIRK交换设备使用 IRK 和随机数生成可解析地址 (48 位): 高 24 位为 hash(IRK, prand), 低 24 位为 prand
已知 IRK 的设备可以验证和解析该地址, 未知 IRK 的设备无法关联不同地址
地址分发通过 GNodeAddress/TNodeAddress 信令完成, 携带地址类型 (联盟分配、第三方本地、联盟预留、私有) 和 6 字节地址。
代码实现: mac.crypto.generate_resolvable_address(kdf_type, irk, rand_part) 和 resolve_address(kdf_type, irk, addr)。
UWB 测量安全 (§9.5)¶
UWB 脉冲测量信号需要专用的安全机制, 防止距离欺骗攻击。
CTS 密钥体系¶
从 Link Key 出发, 派生 UWB 测量专用密钥:
Link Key (16B)
│
└─► SLP Key = KDF(link_key, reserved ‖ "SLP" ‖ zeros)
│
├─► ctsInitContent = KDF(SLP, "ctsInitC" ‖ inputContext)
│ └─► ctsContent32Bit = ctsInitContent 低 32 位
│
├─► ctsKey = KDF(SLP, "ctsK" ‖ ctsContent)
├─► ctsValue = KDF(SLP, "ctsV" ‖ ctsContent)
└─► ctsGap = KDF(SLP, "ctsGapK" ‖ ctsContent)
inputContext (§9.5, 表 71)¶
128 位上下文参数, 编码测量会话的物理层配置:
物理信道号
测距方法和模式
NMSS 采样数
G 节点 L2 ID
天线配置
其他保留位
密钥更新¶
每次测量会话结束后, ctsContent32Bit 递增, 重新派生三个密钥。这确保每次测量使用不同的加扰序列。
TGap 计算 (§9.5.4)¶
TGap 控制 CTS 符号间的时间间隔, 从 ctsGap 的 128 位值中按偏移截取 10 位:
其中 \(T_{offset}\) 由 ctsGap 对应位计算。
CTS 符号生成 (§9.5.5)¶
CTS 符号序列用于 UWB 测量帧的时域加扰:
对每个符号, 用 ctsKey 进行 ECB 加密生成加扰块
提取符号索引和 SC 值 (+1 或 -1)
ctsVCounter 逐符号递增
代码实现: phy.uwb_measurement_security 模块:
UWBMeasInputContext: 128 位上下文编码CTSKeys: 密钥组容器derive_slp_key(),derive_cts_keys(),update_cts_keys()compute_tgap(): TGap 时间间隔计算generate_cts_symbols(): CTS 符号序列生成