Files
banban/docs/talkingq_wss.md
T
chenjintao 3a0714c735 Accelerate legacy WSS elliptic-curve operations and time TLS phases
Enable mbedTLS NIST modular reduction and report per-phase handshake timings. Add handshake-loop regression tests and a certificate verification benchmark, and document the full kernel and APP package requirement.
2026-09-16 14:38:43 +08:00

11 KiB
Raw Blame History

旧板 WSS 适配与联调

本次修改位于 legacy-board-wss(基于 legacy-board),默认地址为 wss://banban.api.talkingq.com:443/ws。沿用无 GNSS、默认音量 100 的旧板配置。上板暴露内核缺少 ECDSA 后,已补齐内核 TLS 能力并统一 APP/内核配置;本次必须更新内核和 APP。

后台实测(2026-09-16)

地址 结果
wss://banban.api.talkingq.com:443/ws 11:32 复测:TLS 1.2、证书链、域名、WebSocket Accept 校验通过,返回 HTTP 101;此前 404 已解决
wss://banban.api.talkingq.com:8080/ws TLS 握手失败,端口未提供可用的 TLS 服务
ws://banban.api.talkingq.com:8080/ws 明文 Upgrade 返回 HTTP 101,Accept 值正确

8080 当前是明文 WebSocket 服务,443 的 WSS 入口已可用。测试没有发送设备身份或业务数据,也没有修改服务器。

若 nginx 与 8080 服务部署在同一主机,可在现有 listen 443 ssl 的域名配置中参考以下转发(由后台按真实部署调整):

location /ws {
    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_read_timeout 300s;
}

可重新运行 powershell.exe -NoProfile -ExecutionPolicy Bypass -File tools\probe_talkingq_wss.ps1。必须得到有效 HTTP 101 和匹配的 Sec-WebSocket-Accept;仅 HTTPS 打得开或证书正常不代表 WebSocket 已可用。

上板 -9774 的修复

11:42 日志中,联网和 MQTT 正常,WSS 在解析根 CA 时返回 -9774(-0x262E:未知签名算法)。ISRG Root X2 使用 ECDSA/SHA-384,原内核 mini TLS 配置没有编译 ECDSA。此前主机 OpenSSL 验证通过,仅能证明证书链有效,不能证明内核支持它。

  • 新增 ql-config/config/talkingq_mbedtls_config.h,由 APP 和内核 mini profile 共用;增加 ECDSA、ECDHE-ECDSA、AES-GCM 和证书日期校验。
  • 内核缺失的 mbedtls/ecdsa.h 从 APP 中同版本 2.28.9 SDK 头文件补入。
  • ARMCC 编译内核头文件、GCC 编译 APP 头文件,对比 10 种 TLS 类型的大小和关键字段偏移,防止调用内核 API 时结构体布局不一致。
  • 内核的 GetCurrentCompTime() 在此产品上是空 shim。X.509 时间检查改用 mbedtls_time() 的真实 RTC 时间和 UTC 转换,保留证书日期验证。
  • 日志增加失败阶段及十六进制错误码;CA 解析成功会输出 WSS root CA parsed successfully。

不能仅刷 APP 修复本次问题,也不能只用未修改配置的旧内核重新打包。

固件行为

2026-09-16 14:06 板端已通过根 CA 解析、TLS 握手、服务器证书和域名校验。后续 recv data failed / HTTP 0 定位到 APP 接收函数:TLS 返回 WANT_READ/WANT_WRITE 后跳出循环,错误变量仍为初始值 -1,导致误断线。现已在该分支明确清除错误状态,由原握手循环继续等待;真实 EOF、TLS 错误和握手超时仍会结束连接。

  • inc/talkingq_wss.h 集中定义默认地址。解析独立处理域名、端口、路径,默认端口 443、无路径时默认 /ws;拒绝明文 URL、非法端口、过长字段和 CR/LF 注入。现有存储容量为 64 字节;不支持 IPv6 字面量。
  • hal_os_get_talkingq_url() 在没有保存地址、或保存值与已知旧默认地址完全匹配时,返回新默认 WSS 地址。此迁移在读取时生效,不改写 Flash。自定义地址保留;自定义明文地址会明确失败,不自动降级。
  • 启用 librws 的 mbedTLS 实现,统一公共和私有头文件中的宏。TCP 继续使用现有蜂窝 PDP profile 1,避免 SDK 定制 mbedtls_net_connect 的 CID/端口 ABI 差异。
  • 设置 SNI 和预期服务器域名,使用 MBEDTLS_SSL_VERIFY_REQUIRED 和 TLS 1.2 下限。没有客户端证书、客户端私钥或双向 TLS。
  • 使用现有 NITZ/RTC 时间检查证书有效期;时间明显未初始化会拒绝连接并打印原因。不会通过关闭校验来绕过时间问题。上板需要确认运营商时间同步有效。
  • 修复 TLS 短写、WANT_READ/WANT_WRITE、断线处理与资源清理;TLS 握手最多等待 20 秒,HTTP Upgrade 最多 10 秒,应用连接等待 45 秒。DNS/TCP 调用和任务调度还会消耗时间,45 秒不是所有底层调用的硬性总期限。
  • WSS 每次产生随机 WebSocket nonce,校验 HTTP 101、Upgrade、Connection、对应 Accept;支持拆分到多个 TLS 记录的响应头,保留响应头后的 WebSocket 数据。
  • 连接失败唤醒等待方;超时停止待连接 socket,回调只处理对应 socket。工作任务栈从 4 KiB 增至 16 KiB,给 TLS 证书和密码运算留出空间;仍需上板观察实际栈和堆余量。
  • WebSocket 成功后,仍由原 sendAuthentication() 发送 device_id、serial_number。本次不改变 MQTT、HTTP 下载及其他业务连接。

TLS 握手耗时优化(2026-09-16)

14:20 板端日志中,TCP 在 14:20:39.114 已连接,TLS 在 14:20:48.752 左右完成,约 9.6 秒;HTTP 101 在 14:20:48.894 完成,约再耗时 0.1 秒。原 socket break 仅表示退出 TCP 连接重试循环,现改为 TCP connected; leaving connect loop。这不是固定 10 秒延时,也不是 WebSocket HTTP 握手耗时。

共享 TLS 配置启用 MBEDTLS_ECP_NIST_OPTIM,使用 SDK 自带的 NIST 曲线快速模约减,减少证书 ECDSA 校验和相应 ECDHE 运算的开销。不改变证书信任、域名和日期校验规则,不调整服务器地址、设备鉴权、曲线列表或连接生命周期。

APP 通过 SDK 导出的 mbedtls_ssl_handshake_step 驱动同一 TLS 1.2 握手状态机,保留 WANT 重试和 20 秒超时;仅在 WANT 状态等待,正常状态推进不增加睡眠。每阶段打印 WSS TLS phase ... elapsed=... ms, calls=... ms, retries=...,结束打印 WSS TLS handshake total=... ms。elapsed 是该阶段总时间,calls 是 SDK 调用内累计经过时间(含任务调度,并非纯 CPU 时间),retries 是等待 I/O 的返回次数;时间分辨率为 SDK 的 5 ms tick。证书和密钥交换阶段仍可能同时包含网络与运算时间,不能单凭阶段名归因。

同一 Windows 主机上用实际 SDK crypto/X.509 源码验证相同证书链,各运行 20 次:关闭 NIST 优化平均 36.8 ms,开启后 10.2 ms,约 3.6 倍。两种配置均通过证书链、错误域名、不可信根、证书日期与 AES-GCM 检查。这是主机算法对比,不是板端总握手时间预测。可运行 tools/test_mbedtls_cert.py --compare-nist 复测;tools/test_wss_handshake.py 验证计时握手循环的状态推进、WANT、真实错误、超时与 tick 回绕。

最新包是 artifacts/wss/tls-speed/EG800AKCN_11LG-legacy-wss-fast.zip,本次需要重新编译并烧录内核和 APP。recv-fix 包保留为已上板通过的回退版本。优化包仍需采集阶段日志确认实际收益;若主要耗时在网络等待,再评估会话恢复或提前连接,不能用主机基准推断网络影响。

根证书来源与验证

固件内置的是公共根 CA ISRG Root X2,不是短期服务器证书。

  • 来源:对目标域名进行 Windows 系统信任和域名校验后导出的证书链根。
  • 根证书 DER SHA-256:69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470。
  • 根证书有效期到 2040-09-17。
  • 实测链:banban.api.talkingq.com → Let's Encrypt YE1 → Root YE(由 X2 交叉签名)→ ISRG Root X2。
  • 当前服务器证书有效期:2026-08-28 至 2026-11-26。后台正常续期且仍能链到内置根时,不需要随服务器证书续期更新固件。
  • Python/OpenSSL 仅加载从固件源码提取的这一张根 CA,没有加载系统证书库或自动下载中间证书,TLS 1.2 验证成功;错误域名和空信任库均验证失败。
  • 固件进行证书链、有效期和域名验证;未增加 OCSP/CRL 吊销查询。后端更换到其他根 CA 时,需要评估并更新信任根。

可重跑:ql-cross-tool\win32\owtoolchain\Python\python.exe tools\probe_wss_root.py。该测试验证服务器链完整性和内置信任根,不能代替板端 mbedTLS 实测。

构建与验证

tools\test_wss.cmd
ql-cross-tool\win32\owtoolchain\Python\python.exe tools\check_mbedtls_abi.py
build.bat kernel
build.bat app
build.bat firmware

主机测试使用 MSVC 编译实际 URL 和握手解析源码;另从真实实现提取 TLS 写入和取消连接函数,注入桩测试短写、重试、超时、时钟回绕和资源释放。tools/test_wss_receive.py 提取实际接收和握手等待函数,结合实际 HTTP 解析器验证 WANT_READ/WANT_WRITE、分片 101、响应后帧数据保留、超时和时钟回绕、EOF/真实错误、空 TLS 上下文及错误 Accept;修复前可复现误断线,修复后通过。解析测试覆盖合法地址、非法端口、明文拒绝、缓冲区边界、旧地址识别、每个响应头分片边界、非 101、错误/重复 Accept、缺失 Upgrade/Connection 和响应大小上限。

在 Visual Studio 开发者终端运行 ql-cross-tool\win32\owtoolchain\Python\python.exe tools\test_mbedtls_cert.py,使用 SDK 实际 crypto/X.509 源码和共享配置验证内置根 CA、当前服务器证书链、错误域名、空信任库、过期/尚未生效日期,以及 AES-GCM 标准测试向量。测试中的分配器、UTC 时钟和日志适配到 Windows,文件读取由测试程序完成;没有替换证书算法实现。默认使用 artifacts/wss/retest-443/chain-0.pem 至 chain-2.pem,可把探测输出目录作为脚本参数。

导出到下述路径后运行 ql-cross-tool\win32\owtoolchain\Python\python.exe tools\verify_wss_package.py,核对 ZIP CRC、APP/内核与当前构建的字节一致性、无 GNSS 入口以及内核 ECDSA/GCM/日期校验符号。SDK 有既有编译警告,不能仅凭外层批处理退出码认定成功。

最新优化包位于 artifacts/wss/tls-speed/EG800AKCN_11LG-legacy-wss-fast.zip,标准输出为 target/EG800AKCN_11LG/EG800AKCN_11LG.zip,两者字节一致。这是完整多分区烧录包。本次新增内核 NIST 加速,需依次 build.bat kernel、build.bat app、build.bat firmware,不能仅更新 APP。运行 ql-cross-tool\win32\owtoolchain\Python\python.exe tools\verify_wss_package.py 校验默认最新包;也可显式传入该 ZIP 路径。

ecc-fix/EG800AKCN_11LG-legacy-wss-ecc.zip 保留用于对照接收错误。原 artifacts/wss/EG800AKCN_11LG-legacy-wss.zip 存在缺失 ECDSA 的问题,请勿用于验证本次修复。旧板明文 WS 包仍保留在 artifacts/legacy-no-gnss/。

上板验收

443 /ws 已通过主机握手测试;ECC/RTC 和接收修复已在板端通过 TLS、HTTP 101,用户确认功能正常。本次 NIST 加速/计时包仍需上板检查:

  1. 无 GNSS 旧板正常启动、蜂窝网络就绪、RTC 时间正确。
  2. 先出现 WSS root CA parsed successfully,再出现 WSS TLS handshake and certificate/hostname verification passed。
  3. 出现 WebSocket upgrade verified: HTTP 101 和 ws connect okay。
  4. 服务器确认原设备鉴权成功,再测试收发音频、断网重连和休眠唤醒。
  5. 记录 WSS TLS phase 和 WSS TLS handshake total,同一网络环境多次对比原约 9.6 秒的 TLS 握手耗时。

TLS 成功、WebSocket 成功、设备鉴权成功是三个不同阶段,不能只看其中一条日志就认定业务已跑通。