高通 QCC2072 在 Android 16 平台对于 802.1X 场景下的支持
测试模组 : O2072PM / O2072PB(QCC2072 Wi-Fi 7)
平台: RK3588 + Android 16
一、背景与功能需求
Android 16 为 Google 较新的平台版本,其自带的 wpa_supplicant(版本 2.11,2024 年 7 月发布)已具备基础 MLO 支持(约 70% 代码),但不足以完整支持 Wi-Fi 7 MLO(多链路操作)在企业网(802.1X/EAP)场景下的全部功能。
本文从功能需求、代码分析、解决方案三部分,讲解如何处理高通 QCC2072 Wi-Fi 7 模组在 Android 16 平台上对 802.1X/EAP 场景的支持。
二、代码分析
Android 16 的 wpa_supplicant 版本为 2.11,具备基础的 MLO 支持。但通过 wpa_supplicant 官方 Hostap 仓库查询可知,upstream 在 MLO 方面做了大量更新。下载 upstream 2.12 分支后,对比核心 MLO 功能差异如下:
| 维度 | Android 16 (2.11) | Upstream 2.12 增强 |
|---|---|---|
| MLO 链路验证 | 仅拷贝 bss->valid_links,无任何验证 |
wpa_bss_get_usable_links() --- 完整 RSNE / MLD capa / EML capa / ext-MLD capa 逐链路验证 |
struct wpa_bss MLD 字段 |
mld_addr + mld_link_id + valid_links + mld_links[] |
+ mld_bss_non_transmitted + mld_capa + ext_mld_capa + eml_capa + max_cw |
| SSID 保护 | ❌ 无 wpa_sm_set_ssid() |
✅ 4-Way Handshake 中验证 SSID 包含在密钥派生中 |
| PMKSA KCK 存储 | ❌ 不存储 KCK | ✅ 存储 KCK + kck_len,支持 SAE PMKSA 缓存 |
| PMKSA 过期重认证 (SAE) | 完全跳过 SAE PMKSA reauth | ✅ 支持 SAE reauth(含去重 sae_reauth_scheduled) |
| 802.1X EAP 状态清理 | ❌ 无 sme_802_1x_auth_data_free() |
✅ 断开时主动释放 EAP 认证数据 |
| 802.11 标准版本 | 802.11-2016 基线 | 802.11-2024 基线(含 MLO 专用状态码 130-135, 152-159) |
| BSS 查找 API | wpa_bss_get() |
+ wpa_bss_get_connection() + wpa_bss_get_ie_beacon() |
| ML Probe 机制 | ✅ 有(含 SSID 匹配) | ✅ 有(更完善的 mld_bss_non_transmitted 判断) |
| EPPKE 支持 | ❌ 无 | ✅ 关联帧加密 |
| 加密 EAPOL | ❌ 无 | ✅ WPA_PARAM_ENCRYPT_EAPOL_M2 / M4 |
| 802.11r (FT) 快速漫游 | ✅ 完整支持(核心功能等价) | ✅ 完整支持 + ft_prepend_pmkid + ssid_verified 增强 |
2.1 迁移策略
不应简单替换 Android 16 的补丁 ,而应将 upstream 2.12 的架构改进整合到 Android 16 已有修复之上。
优先级 1(必须迁移 --- 安全与稳定性)
| 迁移项 | Upstream 2.12 参考 | Android 16 修改文件 | 复杂度 |
|---|---|---|---|
wpa_bss_get_usable_links() |
bss.c:1796 |
bss.c + bss.h |
⭐⭐⭐ |
struct wpa_bss MLD capa 字段 |
bss.h:109-131 |
bss.h + bss.c(解析填充) |
⭐⭐ |
sme_802_1x_auth_data_free() |
sme.c:384 + sme.c:5089 |
sme.c |
⭐ |
wpa_sm_set_ssid() |
wpa.h:211 + wpa.c:4857 |
wpa.h + wpa.c + 调用点(sme.c + wpa_supplicant.c) |
⭐⭐ |
wpas_sme_set_mlo_links() 重构 |
sme.c:856 |
sme.c |
⭐⭐⭐ |
wpas_reset_mlo_info() 内存修复 |
events.c:346 |
events.c |
⭐ |
优先级 2(建议迁移 --- 诊断与可靠性)
| 迁移项 | Upstream 2.12 参考 | 复杂度 |
|---|---|---|
| 802.11-2024 MLO 状态码 | ieee802_11_defs.h |
⭐ |
PMKSA KCK 存储 + auth_alg |
pmksa_cache.h + pmksa_cache.c |
⭐⭐ |
wpa_bss_get_connection() |
bss.c:322 + bss.h:174 |
⭐ |
wpa_bss_get_ie_beacon() |
bss.c:1350 + bss.h:187 |
⭐ |
for_each_link_default() 宏 |
common.h:633 |
⭐ |
mld_bss_non_transmitted 字段 |
bss.h:132 |
⭐ |
| SSID 保护动态配置逻辑 | wpa_supplicant.c:~2291 |
⭐⭐ |
优先级 3(可选迁移 --- 功能增强)
| 迁移项 | 复杂度 | 说明 |
|---|---|---|
| EPPKE 支持 | ⭐⭐⭐ | 关联帧加密,需要驱动侧配合 |
| 加密 EAPOL | ⭐⭐ | 4-Way Handshake 安全增强 |
PMKSA sae_reauth_scheduled |
⭐ | SAE PMKSA 重认证去重 |
三、解决方案:迁移后仍可能遇到的问题
完成 upstream 代码迁移后,可连接 WPA3-Enterprise(PEAP)路由器。但在测试 Cisco Wi-Fi 7 路由器 + RADIUS 的 MLO 多 AP 切换场景时,仍可能遇到以下 3 类问题。
3.1 EAPOL 发送目标地址错误
现象:
关联成功 → EAP 启动 → EAP Identity 请求/响应 → AP 重传 Identity 请求 → 超时断开
关键日志:
nl80211: AP MLD MAC Address mac1
nl80211: MLO link[1] addr mac bssid mac2
l2_packet_receive: src=mac1 ← EAPOL 从 MLD 地址接收
TX EAPOL: dst=mac2 ← 🔴 EAPOL 发送到 BSSID(错误!)
EAP: Received EAP-Request id=148 (retransmit) ← AP 未收到响应,重传
根因 :在 MLO 连接中,EAPOL 帧必须使用 AP MLD MAC 地址 作为目标地址,而非 per-link BSSID。AOSP 的 wpa_supplicant_eapol_send() 无条件使用 wpa_s->bssid。
| 代码路径 | AOSP(修复前) | 正确做法 |
|---|---|---|
| bssid 已设置 | dst = wpa_s->bssid |
dst = wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid |
| bssid 未设置 | dst = bssid(仅查询 BSSID) |
先查询 wpas_drv_get_sta_mlo_info(),MLO 时用 ap_mld_addr |
修复 (wpa_supplicant/wpas_glue.c):
- 添加
struct driver_sta_mlo_info drv_mlo;局部变量 - bssid 未设置路径:调用
wpas_drv_get_sta_mlo_info()获取 MLO 信息,MLO 时使用drv_mlo.ap_mld_addr - bssid 已设置路径:
dst = wpa_s->valid_links ? wpa_s->ap_mld_addr : wpa_s->bssid;
3.2 非 MLO SSID 误用 MLD 地址
现象 :修复 3.1 后,同一台 Cisco MLO 路由器上的非 MLO SSID 无法连接。
根因 :在 wpa_supplicant/sme.c 的 wpas_ml_element() 函数中,valid_links 被无条件设置为非零值:
c
// 修复前 (AOSP 原版)
wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id); // 无条件设置!
...
rnr_ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
if (!rnr_ie) {
ret = true; // 即使没有 RNR 也返回 true
goto out;
}
// RNR 循环中,只有 SSID 匹配的邻居才加入 valid_links
...
ret = true; // 始终返回 true
对于 MLO 能力 AP 上的非 MLO SSID:
- BSS 信标中仍有 Basic ML element(AP 级能力宣告)
- RNR 中存在邻居条目,但这些邻居属于其他 SSID
wpa_scan_res_match()因 SSID 不匹配而跳过邻居- 但
valid_links已被设为非零值 →wpas_glue.c中使用了错误的 MLD 地址
修复:
- 移除
wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id)无条件赋值 - 改为
wpa_s->valid_links = 0,仅 RNR 循环中 SSID 匹配后添加邻居链路 - RNR 循环后按
valid_links是否有邻居链路决定返回值 - RNR 循环 SSID 匹配改用函数参数
ssid(而非wpa_s->current_ssid) - 无 RNR 分支:设置单链路
valid_links+ BSSID/freq
3.3 跨 SSID PMKSA 缓存污染
现象 :同一 MLO 路由器上不同 SSID 切换时,PMKSA 缓存中的旧 PMK 被用于新 SSID 的 4-Way Handshake,导致 4WAY_HANDSHAKE_TIMEOUT (reason=15)。
修复原理:
修复前:
PMKID = HMAC(PMK, "PMK Name" || AA || SPA)
→ 不包含 SSID → 不同 SSID 可能产生相同 PMKID
修复后:
PMKID 仍为 HMAC(PMK, "PMK Name" || AA || SPA) [802.11 标准]
+ SSID 保护:
PTK = PRF(PMK, "Pairwise key expansion",
MIN(AA,SPA) || MAX(AA,SPA) ||
MIN(ANonce,SNonce) || MAX(ANonce,SNonce) ||
SSID) ← SSID 参与 PTK 派生
→ 即使 PMKID 碰撞,PTK 也会不同 → MIC 验证失败 → 安全拒绝
修复清单:
| # | 修复项 | 文件 | 说明 |
|---|---|---|---|
| 1 | wpa_sm_set_ssid() 调用点 |
wpa_supplicant.c + sme.c |
关联完成后将 SSID 注入 wpa_sm,使 SSID 参与 PTK 派生 |
| 2 | SSID 保护动态启用 | wpa_supplicant.c |
根据 AP RSNXE 中的 WLAN_RSNX_CAPAB_SSID_PROTECTION 位自动启用 |
| 3 | WLAN_RSNX_CAPAB_SSID_PROTECTION (21) |
ieee802_11_defs.h ×2 |
新增 RSNXE 能力位定义 |
四、总结
从 QCC2072 Wi-Fi 7 模组调试连接 MLO Wi-Fi 7 WPA3 路由器的经验来看,驱动层在各种加密协议下的组包能力是完整的。真正连接路由器出现异常的原因在于 wpa_supplicant 的 MLO 功能不够完善,需要从 upstream 2.12 做代码迁移才能完整支持 MLO Wi-Fi 7 WPA3 路由器。
迁移注意事项:
- 不要涉及 AIDL / HAL 接口变更
- 不增加新的网络配置项(如
ssid->ssid_protection),改为自动检测 AP 能力 - 所有修改仅限 wpa_supplicant 内部逻辑,避免影响整个 WPA 运行框架