Fix legacy WSS certificate support and receive retries
Share the APP/kernel TLS profile, enable ECDSA and AES-GCM, and use RTC time for certificate validation. Fix WANT_READ/WANT_WRITE handling during WebSocket upgrade and add ABI, certificate, and receive regression checks.
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
# 旧板 WSS 联调包
|
||||
|
||||
`EG800AKCN_11LG-legacy-wss.zip` 是供无 GNSS 旧板联调的完整多分区烧录包,默认连接 `wss://banban.api.talkingq.com:443/ws`。默认音量仍为 100(已有保存值按原逻辑读取)。
|
||||
最新修复包为 `recv-fix/EG800AKCN_11LG-legacy-wss-recv.zip`,供无 GNSS 旧板联调,默认连接 `wss://banban.api.talkingq.com:443/ws`。默认音量仍为 100(已有保存值按原逻辑读取)。这是包含 ECC/RTC 内核和新 APP 的完整多分区包。
|
||||
|
||||
APP 编译和主机测试已通过;具体校验与 SHA-256 见本目录生成的 `verification.json`。没有进行上板验证。
|
||||
2026-09-16 14:06 板端日志已确认 ECC/RTC 修复后的根 CA 解析、TLS 握手、证书和域名校验通过。随后发现 HTTP Upgrade 等待时将 TLS WANT_READ/WANT_WRITE 误判为错误;最新 APP 已修正。实际接收/握手函数回归测试、APP 编译和包校验通过,具体 SHA-256 见 `recv-fix/verification.json`;接收修复仍待上板验证。
|
||||
|
||||
2026-09-16 后台实测:443 证书有效,但 `/ws` Upgrade 返回 404;8080 明文 WS 返回 101,WSS 握手失败。这个包当前不能被标记为已完成 WSS 业务联调。后台修复 TLS 入口转发后才能继续验收。
|
||||
2026-09-16 11:32 复测:443 `/ws` 已返回 HTTP 101,TLS 和证书校验通过;8080 仍是明文 WS。本目录原 `EG800AKCN_11LG-legacy-wss.zip` 缺少 ECDSA,`ecc-fix` 包存在接收误判,均保留作对照;请使用 `recv-fix` 下的新包验证。
|
||||
|
||||
原旧板包保留在 `../legacy-no-gnss/`。构建日志、探测 JSON、导出的公共证书和包体在此目录本地保存并被 Git 忽略。源码和详细步骤见 `../../docs/talkingq_wss.md`。
|
||||
|
||||
+29
-9
@@ -1,16 +1,16 @@
|
||||
# 旧板 WSS 适配与联调
|
||||
|
||||
本次修改位于 `legacy-board-wss`(基于 `legacy-board`),默认地址为 `wss://banban.api.talkingq.com:443/ws`。沿用无 GNSS、默认音量 100 的旧板配置。本次只修改 APP;复用此前支持旧板的内核和其中的 mbedTLS API。
|
||||
本次修改位于 `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` | TLS 1.2、证书链、域名校验通过;WebSocket Upgrade 返回 HTTP 404 |
|
||||
| `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 服务,不能通过把 URL 的 `ws` 改成 `wss` 就获得加密。后台需要在 HTTPS 入口配置 `/ws` 转发,或提供另一个已经启用 TLS 的 WebSocket 入口。404 的准确原因仍需后台检查路由配置。测试没有发送设备身份或业务数据,也没有修改服务器。
|
||||
8080 当前是明文 WebSocket 服务,443 的 WSS 入口已可用。测试没有发送设备身份或业务数据,也没有修改服务器。
|
||||
|
||||
若 nginx 与 8080 服务部署在同一主机,可在现有 `listen 443 ssl` 的域名配置中参考以下转发(由后台按真实部署调整):
|
||||
|
||||
@@ -25,10 +25,24 @@ location /ws {
|
||||
}
|
||||
```
|
||||
|
||||
修复后重新运行 `powershell.exe -NoProfile -ExecutionPolicy Bypass -File tools\probe_talkingq_wss.ps1`。必须得到有效 HTTP 101 和匹配的 `Sec-WebSocket-Accept`;仅 HTTPS 打得开或证书正常不代表 WebSocket 已可用。
|
||||
可重新运行 `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 差异。
|
||||
@@ -57,22 +71,28 @@ location /ws {
|
||||
|
||||
```bat
|
||||
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 写入和取消连接函数,注入桩测试短写、重试、超时、时钟回绕和资源释放。解析测试覆盖合法地址、非法端口、明文拒绝、缓冲区边界、旧地址识别、每个响应头分片边界、非 101、错误/重复 Accept、缺失 Upgrade/Connection 和响应大小上限。
|
||||
主机测试使用 MSVC 编译实际 URL 和握手解析源码;另从真实实现提取 TLS 写入和取消连接函数,注入桩测试短写、重试、超时、时钟回绕和资源释放。`tools/test_wss_receive.py` 提取实际接收和握手等待函数,结合实际 HTTP 解析器验证 WANT_READ/WANT_WRITE、分片 101、响应后帧数据保留、超时和时钟回绕、EOF/真实错误、空 TLS 上下文及错误 Accept;修复前可复现误断线,修复后通过。解析测试覆盖合法地址、非法端口、明文拒绝、缓冲区边界、旧地址识别、每个响应头分片边界、非 101、错误/重复 Accept、缺失 Upgrade/Connection 和响应大小上限。
|
||||
|
||||
导出后运行 `ql-cross-tool\win32\owtoolchain\Python\python.exe tools\verify_wss_package.py`,核对 ZIP CRC、APP/内核与当前构建的字节一致性、无 GNSS 入口以及 WSS 链接符号。SDK 有既有编译警告,不能仅凭外层批处理退出码认定成功。
|
||||
在 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`,可把探测输出目录作为脚本参数。
|
||||
|
||||
测试包位于 `artifacts/wss/EG800AKCN_11LG-legacy-wss.zip`。这是完整多分区烧录包,不是 APP-only 包。原可回退的旧板包保留在 `artifacts/legacy-no-gnss/`。
|
||||
导出到下述路径后运行 `ql-cross-tool\win32\owtoolchain\Python\python.exe tools\verify_wss_package.py`,核对 ZIP CRC、APP/内核与当前构建的字节一致性、无 GNSS 入口以及内核 ECDSA/GCM/日期校验符号。SDK 有既有编译警告,不能仅凭外层批处理退出码认定成功。
|
||||
|
||||
最新修复测试包位于 `artifacts/wss/recv-fix/EG800AKCN_11LG-legacy-wss-recv.zip`,标准输出为 `target/EG800AKCN_11LG/EG800AKCN_11LG.zip`,两者字节一致。这是完整多分区烧录包,内核与 ECC/RTC 修复包一致,APP 增加接收重试修复。在保留已构建的 ECC/RTC 内核的当前工作区,本次仅需 `build.bat app` 和 `build.bat firmware`;全新工作区仍需先构建内核。校验命令为 `ql-cross-tool\win32\owtoolchain\Python\python.exe tools\verify_wss_package.py artifacts/wss/recv-fix/EG800AKCN_11LG-legacy-wss-recv.zip`。
|
||||
|
||||
`ecc-fix/EG800AKCN_11LG-legacy-wss-ecc.zip` 保留用于对照接收错误。原 `artifacts/wss/EG800AKCN_11LG-legacy-wss.zip` 存在缺失 ECDSA 的问题,请勿用于验证本次修复。旧板明文 WS 包仍保留在 `artifacts/legacy-no-gnss/`。
|
||||
|
||||
## 上板验收
|
||||
|
||||
目前未烧录、未完成设备业务联调,且服务器 443 `/ws` 尚返回 404。确认后台转发修复后,再检查:
|
||||
443 `/ws` 已通过主机握手测试;ECC/RTC 修复已在板端通过 TLS 验证,接收修复包仍需上板检查:
|
||||
|
||||
1. 无 GNSS 旧板正常启动、蜂窝网络就绪、RTC 时间正确。
|
||||
2. 出现 `WSS TLS handshake and certificate/hostname verification passed`。
|
||||
2. 先出现 `WSS root CA parsed successfully`,再出现 `WSS TLS handshake and certificate/hostname verification passed`。
|
||||
3. 出现 `WebSocket upgrade verified: HTTP 101` 和 `ws connect okay`。
|
||||
4. 服务器确认原设备鉴权成功,再测试收发音频、断网重连和休眠唤醒。
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -314,7 +314,11 @@ rws_bool rws_socket_recv(_rws_socket *s)
|
||||
goto _exit;
|
||||
}
|
||||
len = mbedtls_ssl_read(&(s->ssl->ssl_ctx), (unsigned char *)(s->payload_buff), RWS_RECEIVE_BUFF_SIZE);
|
||||
if (len == MBEDTLS_ERR_SSL_WANT_READ || len == MBEDTLS_ERR_SSL_WANT_WRITE) break;
|
||||
if (len == MBEDTLS_ERR_SSL_WANT_READ || len == MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
/* No TLS data yet: let the upgrade loop wait for the next record. */
|
||||
error_number = 0;
|
||||
break;
|
||||
}
|
||||
if (len <= 0) {
|
||||
LOG_E("WSS TLS peer closed or read failed: %d\n", len);
|
||||
s->error = rws_error_new_code_descr(rws_error_code_read_write_socket, "TLS peer closed or read failed");
|
||||
@@ -1848,6 +1852,7 @@ void rws_debug(void *ctx, int level, const char *file, int line, const char *str
|
||||
int rws_ssl_conn(_rws_socket *s)
|
||||
{
|
||||
const char *pers = "talkingq-wss";
|
||||
const char *stage = "allocate TLS context";
|
||||
int ret = -1;
|
||||
unsigned int started;
|
||||
uint32_t flags;
|
||||
@@ -1873,12 +1878,16 @@ int rws_ssl_conn(_rws_socket *s)
|
||||
LOG_E("WSS requires valid network/RTC time before certificate verification\n");
|
||||
goto exit;
|
||||
}
|
||||
stage = "seed RNG";
|
||||
ret = mbedtls_ctr_drbg_seed(&ssl->ctr_drbg, mbedtls_entropy_func,
|
||||
&ssl->entropy, (const unsigned char *)pers, strlen(pers));
|
||||
if (ret != 0) goto exit;
|
||||
stage = "parse root CA";
|
||||
ret = mbedtls_x509_crt_parse(&ssl->cacert, (const unsigned char *)s->server_cert,
|
||||
s->server_cert_len);
|
||||
if (ret != 0) goto exit;
|
||||
LOG_I("WSS root CA parsed successfully\n");
|
||||
stage = "configure TLS";
|
||||
ret = mbedtls_ssl_config_defaults(&ssl->ssl_conf, MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
if (ret != 0) goto exit;
|
||||
@@ -1894,6 +1903,7 @@ int rws_ssl_conn(_rws_socket *s)
|
||||
|
||||
/* Reuse the working PDP profile 1 TCP path. The ASR net_connect API has
|
||||
a vendor-specific CID/port ABI, unlike upstream mbedTLS. */
|
||||
stage = "connect TCP";
|
||||
rws_socket_connect_to_host(s);
|
||||
if (s->socket == RWS_INVALID_SOCKET) {
|
||||
ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
|
||||
@@ -1903,9 +1913,11 @@ int rws_ssl_conn(_rws_socket *s)
|
||||
#ifdef MBEDTLS_WITH_ASR
|
||||
ssl->net_ctx.cid = 1;
|
||||
#endif
|
||||
stage = "set nonblocking TCP";
|
||||
ret = mbedtls_net_set_nonblock(&ssl->net_ctx);
|
||||
if (ret != 0) goto exit;
|
||||
mbedtls_ssl_set_bio(&ssl->ssl_ctx, &ssl->net_ctx, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
stage = "TLS handshake / server certificate";
|
||||
started = ql_rtos_get_systicks();
|
||||
while ((ret = mbedtls_ssl_handshake(&ssl->ssl_ctx)) != 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) goto exit;
|
||||
@@ -1927,7 +1939,7 @@ int rws_ssl_conn(_rws_socket *s)
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
LOG_E("WSS TLS connection failed: %d\n", ret);
|
||||
LOG_E("WSS TLS connection failed at %s: %d (-0x%04x)\n", stage, ret, (unsigned int)-ret);
|
||||
rws_error_delete_clean(&s->error);
|
||||
s->error = rws_error_new_code_descr(rws_error_code_connect_to_host, "TLS connection or certificate verification failed");
|
||||
if (s->ssl) {
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef TALKINGQ_MBEDTLS_CONFIG_H
|
||||
#define TALKINGQ_MBEDTLS_CONFIG_H
|
||||
|
||||
/* Shared by kernel and APP: these options determine public struct layouts.
|
||||
* Retain the vendor mini profile and add verified ECDSA TLS 1.2 support. */
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
#define MBEDTLS_HAVE_TIME_DATE
|
||||
#define MBEDTLS_PLATFORM_TIME_ALT
|
||||
#define TALKINGQ_TLS_USE_RTC_TIME
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_1
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
|
||||
#define MBEDTLS_SSL_RENEGOTIATION
|
||||
#define MBEDTLS_SSL_EXPORT_KEYS
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_GCM_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_DES_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#define MBEDTLS_NET_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA384_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_CERTS_C
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
#define MBEDTLS_FS_IO
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_CHACHAPOLY_C
|
||||
#define MBEDTLS_CHACHA20_C
|
||||
#define MBEDTLS_POLY1305_C
|
||||
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
||||
#define MBEDTLS_ECP_DP_CURVE448_ENABLED
|
||||
|
||||
/* SDK-specific net context and hardware RNG ABI. */
|
||||
#define MBEDTLS_WITH_ASR
|
||||
#define QUECTEL_MBEDTLS_GEU_RANDOM_SUPPORT
|
||||
#endif
|
||||
@@ -4339,86 +4339,7 @@
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#endif
|
||||
#else //mini tls config
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
|
||||
/* mbed TLS feature support */
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_1
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_DES_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#define MBEDTLS_NET_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA384_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
//#define MBEDTLS_SSL_SRV_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
|
||||
/* For test certificates */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_CERTS_C
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
|
||||
/* For testing with compat.sh */
|
||||
#define MBEDTLS_FS_IO
|
||||
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
|
||||
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
|
||||
|
||||
#define MBEDTLS_SSL_RENEGOTIATION
|
||||
#define MBEDTLS_SSL_EXPORT_KEYS
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
#define MBEDTLS_CHACHAPOLY_C
|
||||
#define MBEDTLS_CHACHA20_C
|
||||
#define MBEDTLS_POLY1305_C
|
||||
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
||||
#define MBEDTLS_ECP_DP_CURVE448_ENABLED
|
||||
|
||||
//#define MBEDTLS_DEBUG_C
|
||||
#include "../../../../ql-config/config/talkingq_mbedtls_config.h"
|
||||
|
||||
#endif
|
||||
#if defined(MBEDTLS_USER_CONFIG_FILE)
|
||||
|
||||
@@ -4339,86 +4339,7 @@
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#endif
|
||||
#else //mini tls config
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
|
||||
/* mbed TLS feature support */
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_1
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_DES_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#define MBEDTLS_NET_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA384_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
//#define MBEDTLS_SSL_SRV_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
|
||||
/* For test certificates */
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_CERTS_C
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
|
||||
/* For testing with compat.sh */
|
||||
#define MBEDTLS_FS_IO
|
||||
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
|
||||
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
|
||||
|
||||
#define MBEDTLS_SSL_RENEGOTIATION
|
||||
#define MBEDTLS_SSL_EXPORT_KEYS
|
||||
#define MBEDTLS_PLATFORM_MEMORY
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
#define MBEDTLS_CHACHAPOLY_C
|
||||
#define MBEDTLS_CHACHA20_C
|
||||
#define MBEDTLS_POLY1305_C
|
||||
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
||||
#define MBEDTLS_ECP_DP_CURVE448_ENABLED
|
||||
|
||||
//#define MBEDTLS_DEBUG_C
|
||||
#include "../../../../../ql-config/config/talkingq_mbedtls_config.h"
|
||||
|
||||
#endif
|
||||
#if defined(MBEDTLS_USER_CONFIG_FILE)
|
||||
|
||||
@@ -0,0 +1,612 @@
|
||||
/**
|
||||
* \file ecdsa.h
|
||||
*
|
||||
* \brief This file contains ECDSA definitions and functions.
|
||||
*
|
||||
* The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in
|
||||
* <em>Standards for Efficient Cryptography Group (SECG):
|
||||
* SEC1 Elliptic Curve Cryptography</em>.
|
||||
* The use of ECDSA for TLS is defined in <em>RFC-4492: Elliptic Curve
|
||||
* Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)</em>.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright The Mbed TLS Contributors
|
||||
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_ECDSA_H
|
||||
#define MBEDTLS_ECDSA_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/md.h"
|
||||
|
||||
/**
|
||||
* \brief Maximum ECDSA signature size for a given curve bit size
|
||||
*
|
||||
* \param bits Curve size in bits
|
||||
* \return Maximum signature size in bytes
|
||||
*
|
||||
* \note This macro returns a compile-time constant if its argument
|
||||
* is one. It may evaluate its argument multiple times.
|
||||
*/
|
||||
/*
|
||||
* Ecdsa-Sig-Value ::= SEQUENCE {
|
||||
* r INTEGER,
|
||||
* s INTEGER
|
||||
* }
|
||||
*
|
||||
* For each of r and s, the value (V) may include an extra initial "0" bit.
|
||||
*/
|
||||
#define MBEDTLS_ECDSA_MAX_SIG_LEN(bits) \
|
||||
(/*T,L of SEQUENCE*/ ((bits) >= 61 * 8 ? 3 : 2) + \
|
||||
/*T,L of r,s*/ 2 * (((bits) >= 127 * 8 ? 3 : 2) + \
|
||||
/*V of r,s*/ ((bits) + 8) / 8))
|
||||
|
||||
/** The maximal size of an ECDSA signature in Bytes. */
|
||||
#define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN(MBEDTLS_ECP_MAX_BITS)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief The ECDSA context structure.
|
||||
*
|
||||
* \warning Performing multiple operations concurrently on the same
|
||||
* ECDSA context is not supported; objects of this type
|
||||
* should not be shared between multiple threads.
|
||||
*/
|
||||
typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
|
||||
/**
|
||||
* \brief Internal restart context for ecdsa_verify()
|
||||
*
|
||||
* \note Opaque struct, defined in ecdsa.c
|
||||
*/
|
||||
typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx;
|
||||
|
||||
/**
|
||||
* \brief Internal restart context for ecdsa_sign()
|
||||
*
|
||||
* \note Opaque struct, defined in ecdsa.c
|
||||
*/
|
||||
typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx;
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
/**
|
||||
* \brief Internal restart context for ecdsa_sign_det()
|
||||
*
|
||||
* \note Opaque struct, defined in ecdsa.c
|
||||
*/
|
||||
typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief General context for resuming ECDSA operations
|
||||
*/
|
||||
typedef struct {
|
||||
mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and
|
||||
shared administrative info */
|
||||
mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */
|
||||
mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */
|
||||
#endif
|
||||
} mbedtls_ecdsa_restart_ctx;
|
||||
|
||||
#else /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
/* Now we can declare functions that take a pointer to that */
|
||||
typedef void mbedtls_ecdsa_restart_ctx;
|
||||
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
/**
|
||||
* \brief This function checks whether a given group can be used
|
||||
* for ECDSA.
|
||||
*
|
||||
* \param gid The ECP group ID to check.
|
||||
*
|
||||
* \return \c 1 if the group can be used, \c 0 otherwise
|
||||
*/
|
||||
int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid);
|
||||
|
||||
/**
|
||||
* \brief This function computes the ECDSA signature of a
|
||||
* previously-hashed message.
|
||||
*
|
||||
* \note The deterministic version implemented in
|
||||
* mbedtls_ecdsa_sign_det() is usually preferred.
|
||||
*
|
||||
* \note If the bitlength of the message hash is larger than the
|
||||
* bitlength of the group order, then the hash is truncated
|
||||
* as defined in <em>Standards for Efficient Cryptography Group
|
||||
* (SECG): SEC1 Elliptic Curve Cryptography</em>, section
|
||||
* 4.1.3, step 5.
|
||||
*
|
||||
* \see ecp.h
|
||||
*
|
||||
* \param grp The context for the elliptic curve to use.
|
||||
* This must be initialized and have group parameters
|
||||
* set, for example through mbedtls_ecp_group_load().
|
||||
* \param r The MPI context in which to store the first part
|
||||
* the signature. This must be initialized.
|
||||
* \param s The MPI context in which to store the second part
|
||||
* the signature. This must be initialized.
|
||||
* \param d The private signing key. This must be initialized.
|
||||
* \param buf The content to be signed. This is usually the hash of
|
||||
* the original data to be signed. This must be a readable
|
||||
* buffer of length \p blen Bytes. It may be \c NULL if
|
||||
* \p blen is zero.
|
||||
* \param blen The length of \p buf in Bytes.
|
||||
* \param f_rng The RNG function. This must not be \c NULL.
|
||||
* \param p_rng The RNG context to be passed to \p f_rng. This may be
|
||||
* \c NULL if \p f_rng doesn't need a context parameter.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return An \c MBEDTLS_ERR_ECP_XXX
|
||||
* or \c MBEDTLS_MPI_XXX error code on failure.
|
||||
*/
|
||||
int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
|
||||
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
#if defined(MBEDTLS_DEPRECATED_WARNING)
|
||||
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
#define MBEDTLS_DEPRECATED
|
||||
#endif
|
||||
/**
|
||||
* \brief This function computes the ECDSA signature of a
|
||||
* previously-hashed message, deterministic version.
|
||||
*
|
||||
* For more information, see <em>RFC-6979: Deterministic
|
||||
* Usage of the Digital Signature Algorithm (DSA) and Elliptic
|
||||
* Curve Digital Signature Algorithm (ECDSA)</em>.
|
||||
*
|
||||
* \note If the bitlength of the message hash is larger than the
|
||||
* bitlength of the group order, then the hash is truncated as
|
||||
* defined in <em>Standards for Efficient Cryptography Group
|
||||
* (SECG): SEC1 Elliptic Curve Cryptography</em>, section
|
||||
* 4.1.3, step 5.
|
||||
*
|
||||
* \warning Since the output of the internal RNG is always the same for
|
||||
* the same key and message, this limits the efficiency of
|
||||
* blinding and leaks information through side channels. For
|
||||
* secure behavior use mbedtls_ecdsa_sign_det_ext() instead.
|
||||
*
|
||||
* (Optimally the blinding is a random value that is different
|
||||
* on every execution. In this case the blinding is still
|
||||
* random from the attackers perspective, but is the same on
|
||||
* each execution. This means that this blinding does not
|
||||
* prevent attackers from recovering secrets by combining
|
||||
* several measurement traces, but may prevent some attacks
|
||||
* that exploit relationships between secret data.)
|
||||
*
|
||||
* \see ecp.h
|
||||
*
|
||||
* \param grp The context for the elliptic curve to use.
|
||||
* This must be initialized and have group parameters
|
||||
* set, for example through mbedtls_ecp_group_load().
|
||||
* \param r The MPI context in which to store the first part
|
||||
* the signature. This must be initialized.
|
||||
* \param s The MPI context in which to store the second part
|
||||
* the signature. This must be initialized.
|
||||
* \param d The private signing key. This must be initialized
|
||||
* and setup, for example through mbedtls_ecp_gen_privkey().
|
||||
* \param buf The hashed content to be signed. This must be a readable
|
||||
* buffer of length \p blen Bytes. It may be \c NULL if
|
||||
* \p blen is zero.
|
||||
* \param blen The length of \p buf in Bytes.
|
||||
* \param md_alg The hash algorithm used to hash the original data.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
|
||||
* error code on failure.
|
||||
*/
|
||||
int mbedtls_ecdsa_sign_det(mbedtls_ecp_group *grp, mbedtls_mpi *r,
|
||||
mbedtls_mpi *s, const mbedtls_mpi *d,
|
||||
const unsigned char *buf, size_t blen,
|
||||
mbedtls_md_type_t md_alg) MBEDTLS_DEPRECATED;
|
||||
#undef MBEDTLS_DEPRECATED
|
||||
#endif /* MBEDTLS_DEPRECATED_REMOVED */
|
||||
|
||||
/**
|
||||
* \brief This function computes the ECDSA signature of a
|
||||
* previously-hashed message, deterministic version.
|
||||
*
|
||||
* For more information, see <em>RFC-6979: Deterministic
|
||||
* Usage of the Digital Signature Algorithm (DSA) and Elliptic
|
||||
* Curve Digital Signature Algorithm (ECDSA)</em>.
|
||||
*
|
||||
* \note If the bitlength of the message hash is larger than the
|
||||
* bitlength of the group order, then the hash is truncated as
|
||||
* defined in <em>Standards for Efficient Cryptography Group
|
||||
* (SECG): SEC1 Elliptic Curve Cryptography</em>, section
|
||||
* 4.1.3, step 5.
|
||||
*
|
||||
* \see ecp.h
|
||||
*
|
||||
* \param grp The context for the elliptic curve to use.
|
||||
* This must be initialized and have group parameters
|
||||
* set, for example through mbedtls_ecp_group_load().
|
||||
* \param r The MPI context in which to store the first part
|
||||
* the signature. This must be initialized.
|
||||
* \param s The MPI context in which to store the second part
|
||||
* the signature. This must be initialized.
|
||||
* \param d The private signing key. This must be initialized
|
||||
* and setup, for example through mbedtls_ecp_gen_privkey().
|
||||
* \param buf The hashed content to be signed. This must be a readable
|
||||
* buffer of length \p blen Bytes. It may be \c NULL if
|
||||
* \p blen is zero.
|
||||
* \param blen The length of \p buf in Bytes.
|
||||
* \param md_alg The hash algorithm used to hash the original data.
|
||||
* \param f_rng_blind The RNG function used for blinding. This must not be
|
||||
* \c NULL.
|
||||
* \param p_rng_blind The RNG context to be passed to \p f_rng_blind. This
|
||||
* may be \c NULL if \p f_rng_blind doesn't need
|
||||
* a context parameter.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
|
||||
* error code on failure.
|
||||
*/
|
||||
int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r,
|
||||
mbedtls_mpi *s, const mbedtls_mpi *d,
|
||||
const unsigned char *buf, size_t blen,
|
||||
mbedtls_md_type_t md_alg,
|
||||
int (*f_rng_blind)(void *, unsigned char *, size_t),
|
||||
void *p_rng_blind);
|
||||
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
|
||||
|
||||
/**
|
||||
* \brief This function verifies the ECDSA signature of a
|
||||
* previously-hashed message.
|
||||
*
|
||||
* \note If the bitlength of the message hash is larger than the
|
||||
* bitlength of the group order, then the hash is truncated as
|
||||
* defined in <em>Standards for Efficient Cryptography Group
|
||||
* (SECG): SEC1 Elliptic Curve Cryptography</em>, section
|
||||
* 4.1.4, step 3.
|
||||
*
|
||||
* \see ecp.h
|
||||
*
|
||||
* \param grp The ECP group to use.
|
||||
* This must be initialized and have group parameters
|
||||
* set, for example through mbedtls_ecp_group_load().
|
||||
* \param buf The hashed content that was signed. This must be a readable
|
||||
* buffer of length \p blen Bytes. It may be \c NULL if
|
||||
* \p blen is zero.
|
||||
* \param blen The length of \p buf in Bytes.
|
||||
* \param Q The public key to use for verification. This must be
|
||||
* initialized and setup.
|
||||
* \param r The first integer of the signature.
|
||||
* This must be initialized.
|
||||
* \param s The second integer of the signature.
|
||||
* This must be initialized.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
|
||||
* error code on failure.
|
||||
*/
|
||||
int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,
|
||||
const unsigned char *buf, size_t blen,
|
||||
const mbedtls_ecp_point *Q, const mbedtls_mpi *r,
|
||||
const mbedtls_mpi *s);
|
||||
|
||||
/**
|
||||
* \brief This function computes the ECDSA signature and writes it
|
||||
* to a buffer, serialized as defined in <em>RFC-4492:
|
||||
* Elliptic Curve Cryptography (ECC) Cipher Suites for
|
||||
* Transport Layer Security (TLS)</em>.
|
||||
*
|
||||
* \warning It is not thread-safe to use the same context in
|
||||
* multiple threads.
|
||||
*
|
||||
* \note The deterministic version is used if
|
||||
* #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more
|
||||
* information, see <em>RFC-6979: Deterministic Usage
|
||||
* of the Digital Signature Algorithm (DSA) and Elliptic
|
||||
* Curve Digital Signature Algorithm (ECDSA)</em>.
|
||||
*
|
||||
* \note If the bitlength of the message hash is larger than the
|
||||
* bitlength of the group order, then the hash is truncated as
|
||||
* defined in <em>Standards for Efficient Cryptography Group
|
||||
* (SECG): SEC1 Elliptic Curve Cryptography</em>, section
|
||||
* 4.1.3, step 5.
|
||||
*
|
||||
* \see ecp.h
|
||||
*
|
||||
* \param ctx The ECDSA context to use. This must be initialized
|
||||
* and have a group and private key bound to it, for example
|
||||
* via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
|
||||
* \param md_alg The message digest that was used to hash the message.
|
||||
* \param hash The message hash to be signed. This must be a readable
|
||||
* buffer of length \p hlen Bytes.
|
||||
* \param hlen The length of the hash \p hash in Bytes.
|
||||
* \param sig The buffer to which to write the signature. This must be a
|
||||
* writable buffer of length at least twice as large as the
|
||||
* size of the curve used, plus 9. For example, 73 Bytes if
|
||||
* a 256-bit curve is used. A buffer length of
|
||||
* #MBEDTLS_ECDSA_MAX_LEN is always safe.
|
||||
* \param slen The address at which to store the actual length of
|
||||
* the signature written. Must not be \c NULL.
|
||||
* \param f_rng The RNG function. This must not be \c NULL if
|
||||
* #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise,
|
||||
* it is used only for blinding and may be set to \c NULL, but
|
||||
* doing so is DEPRECATED.
|
||||
* \param p_rng The RNG context to be passed to \p f_rng. This may be
|
||||
* \c NULL if \p f_rng is \c NULL or doesn't use a context.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
|
||||
* \c MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
*/
|
||||
int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
|
||||
mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hlen,
|
||||
unsigned char *sig, size_t *slen,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng);
|
||||
|
||||
/**
|
||||
* \brief This function computes the ECDSA signature and writes it
|
||||
* to a buffer, in a restartable way.
|
||||
*
|
||||
* \see \c mbedtls_ecdsa_write_signature()
|
||||
*
|
||||
* \note This function is like \c mbedtls_ecdsa_write_signature()
|
||||
* but it can return early and restart according to the limit
|
||||
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
|
||||
*
|
||||
* \param ctx The ECDSA context to use. This must be initialized
|
||||
* and have a group and private key bound to it, for example
|
||||
* via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
|
||||
* \param md_alg The message digest that was used to hash the message.
|
||||
* \param hash The message hash to be signed. This must be a readable
|
||||
* buffer of length \p hlen Bytes.
|
||||
* \param hlen The length of the hash \p hash in Bytes.
|
||||
* \param sig The buffer to which to write the signature. This must be a
|
||||
* writable buffer of length at least twice as large as the
|
||||
* size of the curve used, plus 9. For example, 73 Bytes if
|
||||
* a 256-bit curve is used. A buffer length of
|
||||
* #MBEDTLS_ECDSA_MAX_LEN is always safe.
|
||||
* \param slen The address at which to store the actual length of
|
||||
* the signature written. Must not be \c NULL.
|
||||
* \param f_rng The RNG function. This must not be \c NULL if
|
||||
* #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise,
|
||||
* it is unused and may be set to \c NULL.
|
||||
* \param p_rng The RNG context to be passed to \p f_rng. This may be
|
||||
* \c NULL if \p f_rng is \c NULL or doesn't use a context.
|
||||
* \param rs_ctx The restart context to use. This may be \c NULL to disable
|
||||
* restarting. If it is not \c NULL, it must point to an
|
||||
* initialized restart context.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
|
||||
* operations was reached: see \c mbedtls_ecp_set_max_ops().
|
||||
* \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
|
||||
* \c MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
*/
|
||||
int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
|
||||
mbedtls_md_type_t md_alg,
|
||||
const unsigned char *hash, size_t hlen,
|
||||
unsigned char *sig, size_t *slen,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng,
|
||||
mbedtls_ecdsa_restart_ctx *rs_ctx);
|
||||
|
||||
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
|
||||
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
|
||||
#if defined(MBEDTLS_DEPRECATED_WARNING)
|
||||
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
#define MBEDTLS_DEPRECATED
|
||||
#endif
|
||||
/**
|
||||
* \brief This function computes an ECDSA signature and writes
|
||||
* it to a buffer, serialized as defined in <em>RFC-4492:
|
||||
* Elliptic Curve Cryptography (ECC) Cipher Suites for
|
||||
* Transport Layer Security (TLS)</em>.
|
||||
*
|
||||
* The deterministic version is defined in <em>RFC-6979:
|
||||
* Deterministic Usage of the Digital Signature Algorithm (DSA)
|
||||
* and Elliptic Curve Digital Signature Algorithm (ECDSA)</em>.
|
||||
*
|
||||
* \warning It is not thread-safe to use the same context in
|
||||
* multiple threads.
|
||||
*
|
||||
* \note If the bitlength of the message hash is larger than the
|
||||
* bitlength of the group order, then the hash is truncated as
|
||||
* defined in <em>Standards for Efficient Cryptography Group
|
||||
* (SECG): SEC1 Elliptic Curve Cryptography</em>, section
|
||||
* 4.1.3, step 5.
|
||||
*
|
||||
* \see ecp.h
|
||||
*
|
||||
* \deprecated Superseded by mbedtls_ecdsa_write_signature() in
|
||||
* Mbed TLS version 2.0 and later.
|
||||
*
|
||||
* \param ctx The ECDSA context to use. This must be initialized
|
||||
* and have a group and private key bound to it, for example
|
||||
* via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
|
||||
* \param hash The message hash to be signed. This must be a readable
|
||||
* buffer of length \p hlen Bytes.
|
||||
* \param hlen The length of the hash \p hash in Bytes.
|
||||
* \param sig The buffer to which to write the signature. This must be a
|
||||
* writable buffer of length at least twice as large as the
|
||||
* size of the curve used, plus 9. For example, 73 Bytes if
|
||||
* a 256-bit curve is used. A buffer length of
|
||||
* #MBEDTLS_ECDSA_MAX_LEN is always safe.
|
||||
* \param slen The address at which to store the actual length of
|
||||
* the signature written. Must not be \c NULL.
|
||||
* \param md_alg The message digest that was used to hash the message.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
|
||||
* \c MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
*/
|
||||
int mbedtls_ecdsa_write_signature_det(mbedtls_ecdsa_context *ctx,
|
||||
const unsigned char *hash, size_t hlen,
|
||||
unsigned char *sig, size_t *slen,
|
||||
mbedtls_md_type_t md_alg) MBEDTLS_DEPRECATED;
|
||||
#undef MBEDTLS_DEPRECATED
|
||||
#endif /* MBEDTLS_DEPRECATED_REMOVED */
|
||||
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
|
||||
|
||||
/**
|
||||
* \brief This function reads and verifies an ECDSA signature.
|
||||
*
|
||||
* \note If the bitlength of the message hash is larger than the
|
||||
* bitlength of the group order, then the hash is truncated as
|
||||
* defined in <em>Standards for Efficient Cryptography Group
|
||||
* (SECG): SEC1 Elliptic Curve Cryptography</em>, section
|
||||
* 4.1.4, step 3.
|
||||
*
|
||||
* \see ecp.h
|
||||
*
|
||||
* \param ctx The ECDSA context to use. This must be initialized
|
||||
* and have a group and public key bound to it.
|
||||
* \param hash The message hash that was signed. This must be a readable
|
||||
* buffer of length \p hlen Bytes.
|
||||
* \param hlen The size of the hash \p hash.
|
||||
* \param sig The signature to read and verify. This must be a readable
|
||||
* buffer of length \p slen Bytes.
|
||||
* \param slen The size of \p sig in Bytes.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
|
||||
* \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid
|
||||
* signature in \p sig, but its length is less than \p siglen.
|
||||
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX
|
||||
* error code on failure for any other reason.
|
||||
*/
|
||||
int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,
|
||||
const unsigned char *hash, size_t hlen,
|
||||
const unsigned char *sig, size_t slen);
|
||||
|
||||
/**
|
||||
* \brief This function reads and verifies an ECDSA signature,
|
||||
* in a restartable way.
|
||||
*
|
||||
* \see \c mbedtls_ecdsa_read_signature()
|
||||
*
|
||||
* \note This function is like \c mbedtls_ecdsa_read_signature()
|
||||
* but it can return early and restart according to the limit
|
||||
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
|
||||
*
|
||||
* \param ctx The ECDSA context to use. This must be initialized
|
||||
* and have a group and public key bound to it.
|
||||
* \param hash The message hash that was signed. This must be a readable
|
||||
* buffer of length \p hlen Bytes.
|
||||
* \param hlen The size of the hash \p hash.
|
||||
* \param sig The signature to read and verify. This must be a readable
|
||||
* buffer of length \p slen Bytes.
|
||||
* \param slen The size of \p sig in Bytes.
|
||||
* \param rs_ctx The restart context to use. This may be \c NULL to disable
|
||||
* restarting. If it is not \c NULL, it must point to an
|
||||
* initialized restart context.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
|
||||
* \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid
|
||||
* signature in \p sig, but its length is less than \p siglen.
|
||||
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
|
||||
* operations was reached: see \c mbedtls_ecp_set_max_ops().
|
||||
* \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX
|
||||
* error code on failure for any other reason.
|
||||
*/
|
||||
int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx,
|
||||
const unsigned char *hash, size_t hlen,
|
||||
const unsigned char *sig, size_t slen,
|
||||
mbedtls_ecdsa_restart_ctx *rs_ctx);
|
||||
|
||||
/**
|
||||
* \brief This function generates an ECDSA keypair on the given curve.
|
||||
*
|
||||
* \see ecp.h
|
||||
*
|
||||
* \param ctx The ECDSA context to store the keypair in.
|
||||
* This must be initialized.
|
||||
* \param gid The elliptic curve to use. One of the various
|
||||
* \c MBEDTLS_ECP_DP_XXX macros depending on configuration.
|
||||
* \param f_rng The RNG function to use. This must not be \c NULL.
|
||||
* \param p_rng The RNG context to be passed to \p f_rng. This may be
|
||||
* \c NULL if \p f_rng doesn't need a context argument.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return An \c MBEDTLS_ERR_ECP_XXX code on failure.
|
||||
*/
|
||||
int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
|
||||
|
||||
/**
|
||||
* \brief This function sets up an ECDSA context from an EC key pair.
|
||||
*
|
||||
* \see ecp.h
|
||||
*
|
||||
* \param ctx The ECDSA context to setup. This must be initialized.
|
||||
* \param key The EC key to use. This must be initialized and hold
|
||||
* a private-public key pair or a public key. In the former
|
||||
* case, the ECDSA context may be used for signature creation
|
||||
* and verification after this call. In the latter case, it
|
||||
* may be used for signature verification.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return An \c MBEDTLS_ERR_ECP_XXX code on failure.
|
||||
*/
|
||||
int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx,
|
||||
const mbedtls_ecp_keypair *key);
|
||||
|
||||
/**
|
||||
* \brief This function initializes an ECDSA context.
|
||||
*
|
||||
* \param ctx The ECDSA context to initialize.
|
||||
* This must not be \c NULL.
|
||||
*/
|
||||
void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief This function frees an ECDSA context.
|
||||
*
|
||||
* \param ctx The ECDSA context to free. This may be \c NULL,
|
||||
* in which case this function does nothing. If it
|
||||
* is not \c NULL, it must be initialized.
|
||||
*/
|
||||
void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx);
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
/**
|
||||
* \brief Initialize a restart context.
|
||||
*
|
||||
* \param ctx The restart context to initialize.
|
||||
* This must not be \c NULL.
|
||||
*/
|
||||
void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx);
|
||||
|
||||
/**
|
||||
* \brief Free the components of a restart context.
|
||||
*
|
||||
* \param ctx The restart context to free. This may be \c NULL,
|
||||
* in which case this function does nothing. If it
|
||||
* is not \c NULL, it must be initialized.
|
||||
*/
|
||||
void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx);
|
||||
#endif /* MBEDTLS_ECP_RESTARTABLE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ecdsa.h */
|
||||
@@ -959,14 +959,16 @@ int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name)
|
||||
* Set the time structure to the current time.
|
||||
* Return 0 on success, non-zero on failure.
|
||||
*/
|
||||
#ifdef QUECTEL_MBEDTLS_SUPPORT
|
||||
#if defined(QUECTEL_MBEDTLS_SUPPORT) && !defined(TALKINGQ_TLS_USE_RTC_TIME)
|
||||
#include "utlTime.h"
|
||||
#include "saremo_RTC.h"
|
||||
extern void GetCurrentCompTime(TIME *con_time);
|
||||
#endif/*QUECTEL_MBEDTLS_SUPPORT*/
|
||||
static int x509_get_current_time(mbedtls_x509_time *now)
|
||||
{
|
||||
#ifdef QUECTEL_MBEDTLS_SUPPORT
|
||||
/* OpenCPU's GetCurrentCompTime is an empty shim. The shared TLS profile uses
|
||||
* mbedtls_time (SDK RTC) and UTC conversion below instead. */
|
||||
#if defined(QUECTEL_MBEDTLS_SUPPORT) && !defined(TALKINGQ_TLS_USE_RTC_TIME)
|
||||
TIME end_time = {0};
|
||||
GetCurrentCompTime(&end_time);
|
||||
now->year = end_time.year;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
"""Check actual ARMCC kernel / GCC APP TLS layouts and enabled features."""
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import struct
|
||||
import subprocess
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
output = root / 'artifacts/wss/ecc-fix'
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
toolchain = root / 'ql-cross-tool/win32/owtoolchain'
|
||||
gcc = toolchain / 'gcc-arm-none-eabi/bin/arm-none-eabi-gcc.exe'
|
||||
objcopy = gcc.with_name('arm-none-eabi-objcopy.exe')
|
||||
armcc = toolchain / 'ARM_Compiler_5/bin/armcc.exe'
|
||||
types = ['ssl_context', 'ssl_config', 'net_context', 'x509_crt', 'pk_context',
|
||||
'entropy_context', 'ctr_drbg_context', 'ecp_group', 'ecp_point', 'mpi']
|
||||
fields = {'ssl_context': ['conf', 'state', 'in_buf', 'out_buf', 'session', 'handshake', 'hostname'],
|
||||
'ssl_config': ['ca_chain', 'cert_profile', 'f_rng', 'p_rng'],
|
||||
'net_context': ['fd', 'cid'], 'x509_crt': ['pk', 'sig', 'next']}
|
||||
labels = ['sizeof(mbedtls_' + t + ')' for t in types]
|
||||
labels += ['offsetof(mbedtls_' + t + ', ' + f + ')' for t, fs in fields.items() for f in fs]
|
||||
source = output / 'tls_layout.c'
|
||||
source.write_text('#include <stddef.h>\n#include "mbedtls/ssl.h"\n'
|
||||
'#include "mbedtls/net_sockets.h"\n#include "mbedtls/entropy.h"\n'
|
||||
'#include "mbedtls/ctr_drbg.h"\n'
|
||||
'const unsigned int talkingq_tls_layout[] = {\n' + ',\n'.join(labels) + '\n};\n')
|
||||
env = os.environ.copy()
|
||||
env['ARMLMD_LICENSE_FILE'] = str(toolchain / 'license.dat')
|
||||
layouts, macros = {}, {}
|
||||
for target in ['kernel', 'app']:
|
||||
include = root / ('ql-kernel' if target == 'kernel' else 'ql-application') / 'threadx/common/include'
|
||||
obj = output / (target + '-tls-layout.o')
|
||||
flags = ['-I' + str(include), '-DQUECTEL_OPEN_CPU']
|
||||
if target == 'kernel':
|
||||
command = [str(armcc), '--cpu', 'Cortex-R5F', '--fpu=softvfp+vfpv3_d16',
|
||||
'--gnu', '--thumb', '-c', str(source), '-o', str(obj)] + flags
|
||||
section = '.constdata'
|
||||
else:
|
||||
command = [str(gcc), '-mcpu=cortex-r5', '-mthumb', '-mfloat-abi=softfp', '-mfpu=vfpv3-d16',
|
||||
'-c', str(source), '-o', str(obj)] + flags
|
||||
section = '.rodata'
|
||||
subprocess.run(command, env=env, check=True)
|
||||
binary = obj.with_suffix('.bin')
|
||||
subprocess.run([str(objcopy), '-O', 'binary', '-j', section, str(obj), str(binary)], check=True)
|
||||
data = binary.read_bytes()
|
||||
assert len(data) == len(labels) * 4, (target, len(data))
|
||||
layouts[target] = dict(zip(labels, struct.unpack('<' + 'I' * len(labels), data)))
|
||||
defines = subprocess.check_output([str(gcc), '-E', '-dM', '-x', 'c', '-include', 'mbedtls/config.h',
|
||||
'NUL'] + flags, text=True)
|
||||
macros[target] = sorted(line for line in defines.splitlines() if line.startswith('#define MBEDTLS_')
|
||||
or line.startswith('#define QUECTEL_MBEDTLS_'))
|
||||
assert layouts['kernel'] == layouts['app'], json.dumps(layouts, indent=2)
|
||||
assert macros['kernel'] == macros['app'], json.dumps({k: sorted(set(macros[k]) - set(macros['app' if k == 'kernel' else 'kernel'])) for k in macros})
|
||||
for feature in ['ECDSA_C', 'KEY_EXCHANGE_ECDHE_ECDSA_ENABLED', 'GCM_C', 'HAVE_TIME_DATE', 'PLATFORM_TIME_ALT']:
|
||||
assert any(line.startswith('#define MBEDTLS_' + feature + ' ') for line in macros['kernel'])
|
||||
report = {'result': 'PASS', 'layout': layouts['kernel'], 'features': macros['kernel']}
|
||||
(output / 'tls-abi.json').write_text(json.dumps(report, indent=2))
|
||||
print('PASS: ARMCC kernel / GCC APP TLS sizes, field offsets and feature macros agree')
|
||||
print(json.dumps(layouts['kernel'], indent=2))
|
||||
@@ -0,0 +1,84 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include "mbedtls/x509_crt.h"
|
||||
#include "mbedtls/platform_time.h"
|
||||
#include "mbedtls/gcm.h"
|
||||
#include "mbedtls/ssl_ciphersuites.h"
|
||||
#include "talkingq_wss.h"
|
||||
|
||||
void *mbedtls_calloc(size_t n, size_t size) { return calloc(n, size); }
|
||||
void mbedtls_free(void *p) { free(p); }
|
||||
static time_t test_time;
|
||||
static time_t read_test_time(time_t *p) { if (p) *p = test_time; return test_time; }
|
||||
mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *) = read_test_time;
|
||||
void CPUartLogPrintf(const char *format, ...) { (void)format; }
|
||||
int mbedtls_snprintf(char *buffer, size_t size, const char *format, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
result = vsnprintf(buffer, size, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
mbedtls_x509_crt root, chain;
|
||||
mbedtls_gcm_context gcm;
|
||||
uint32_t flags;
|
||||
int ret, i;
|
||||
char path[1024];
|
||||
char pem[16384];
|
||||
FILE *file;
|
||||
size_t length;
|
||||
unsigned char key[16] = {0}, iv[12] = {0}, plain[16] = {0}, cipher[16], tag[16];
|
||||
const unsigned char expected_cipher[16] = {0x03,0x88,0xda,0xce,0x60,0xb6,0xa3,0x92,0xf3,0x28,0xc2,0xb9,0x71,0xb2,0xfe,0x78};
|
||||
const unsigned char expected_tag[16] = {0xab,0x6e,0x47,0xd4,0x2c,0xec,0x13,0xbd,0xf5,0x3a,0x67,0xb2,0x12,0x57,0xbd,0xdf};
|
||||
assert(argc == 2);
|
||||
test_time = time(NULL);
|
||||
mbedtls_x509_crt_init(&root);
|
||||
mbedtls_x509_crt_init(&chain);
|
||||
ret = mbedtls_x509_crt_parse(&root, (const unsigned char *)talkingq_root_ca, talkingq_root_ca_size);
|
||||
printf("SDK root CA parse: %d (previous device failure: -9774)\n", ret);
|
||||
assert(ret == 0);
|
||||
for (i = 0; i < 3; ++i) {
|
||||
snprintf(path, sizeof(path), "%s/chain-%d.pem", argv[1], i);
|
||||
file = fopen(path, "rb");
|
||||
assert(file != NULL);
|
||||
length = fread(pem, 1, sizeof(pem)-1, file);
|
||||
assert(feof(file) && !ferror(file));
|
||||
fclose(file);
|
||||
pem[length] = 0;
|
||||
ret = mbedtls_x509_crt_parse(&chain, (const unsigned char *)pem, length + 1);
|
||||
assert(ret == 0);
|
||||
}
|
||||
ret = mbedtls_x509_crt_verify(&chain, &root, NULL, "banban.api.talkingq.com", &flags, NULL, NULL, 0);
|
||||
printf("SDK server chain + hostname verify: %d, flags=0x%08x\n", ret, (unsigned int)flags);
|
||||
assert(ret == 0 && flags == 0);
|
||||
ret = mbedtls_x509_crt_verify(&chain, &root, NULL, "wrong.invalid", &flags, NULL, NULL, 0);
|
||||
assert(ret != 0 && (flags & MBEDTLS_X509_BADCERT_CN_MISMATCH));
|
||||
ret = mbedtls_x509_crt_verify(&chain, NULL, NULL, "banban.api.talkingq.com", &flags, NULL, NULL, 0);
|
||||
assert(ret != 0 && (flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED));
|
||||
test_time = 1900000000; /* 2030: this server certificate is expired. */
|
||||
ret = mbedtls_x509_crt_verify(&chain, &root, NULL, "banban.api.talkingq.com", &flags, NULL, NULL, 0);
|
||||
assert(ret != 0 && (flags & MBEDTLS_X509_BADCERT_EXPIRED));
|
||||
test_time = 1700000000; /* 2023: this server certificate is not yet valid. */
|
||||
ret = mbedtls_x509_crt_verify(&chain, &root, NULL, "banban.api.talkingq.com", &flags, NULL, NULL, 0);
|
||||
assert(ret != 0 && (flags & MBEDTLS_X509_BADCERT_FUTURE));
|
||||
assert(mbedtls_ssl_ciphersuite_from_id(MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) != NULL);
|
||||
mbedtls_gcm_init(&gcm);
|
||||
assert(mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, key, 128) == 0);
|
||||
assert(mbedtls_gcm_crypt_and_tag(&gcm, MBEDTLS_GCM_ENCRYPT, 16, iv, 12, NULL, 0,
|
||||
plain, cipher, 16, tag) == 0);
|
||||
assert(!memcmp(cipher, expected_cipher, 16) && !memcmp(tag, expected_tag, 16));
|
||||
mbedtls_gcm_free(&gcm);
|
||||
mbedtls_x509_crt_free(&chain);
|
||||
mbedtls_x509_crt_free(&root);
|
||||
puts("PASS: SDK ECDSA certificate chain, hostname, trust, dates, TLS suite and AES-GCM vector");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
"""Build the SDK's real crypto/X.509 sources with MSVC and test the server chain.
|
||||
Run from a Visual Studio developer shell. Chain PEMs come from the WSS probe.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
output = root / 'artifacts/wss/ecc-fix/host-cert'
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
chain = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else root / 'artifacts/wss/retest-443'
|
||||
sources = '''asn1parse asn1write bignum base64 pem oid pk pkparse pk_wrap rsa rsa_internal
|
||||
ecp ecp_curves ecdsa md md5 sha1 sha256 sha512 aes des gcm cipher cipher_wrap
|
||||
chacha20 chachapoly poly1305 constant_time ctr_drbg x509 x509_crt platform_util
|
||||
ecdh ssl_ciphersuites'''.split()
|
||||
command = ['cl', '/nologo', '/O2', '/Gy', '/TC', '/D_CRT_SECURE_NO_WARNINGS',
|
||||
'/DMBEDTLS_CONFIG_FILE="wss_tls_host_config.h"',
|
||||
'/I' + str(root / 'tools'), '/I' + str(root / 'tools/wss_host_stubs'),
|
||||
'/I' + str(root / 'ql-kernel/threadx/common/include'),
|
||||
'/I' + str(root / 'ql-application/threadx/interface/custom_app/inc'),
|
||||
str(root / 'tools/test_mbedtls_cert.c'),
|
||||
str(root / 'ql-application/threadx/interface/custom_app/talkingq_root_ca.c')]
|
||||
command += [str(root / ('ql-kernel/threadx/quec_mbedtls/' + name + '.c')) for name in sources]
|
||||
exe = output / 'test_mbedtls_cert.exe'
|
||||
command += ['/Fe' + str(exe), '/link', '/OPT:REF']
|
||||
subprocess.run(command, cwd=output, check=True)
|
||||
subprocess.run([str(exe), str(chain)], check=True)
|
||||
@@ -10,4 +10,6 @@ if errorlevel 1 exit /b 1
|
||||
artifacts\wss\test_wss.exe
|
||||
if errorlevel 1 exit /b 1
|
||||
ql-cross-tool\win32\owtoolchain\Python\python.exe tools\test_wss_io.py
|
||||
if errorlevel 1 exit /b 1
|
||||
ql-cross-tool\win32\owtoolchain\Python\python.exe tools\test_wss_receive.py
|
||||
exit /b %errorlevel%
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
"""Exercise the real receive/upgrade loop with delayed TLS records."""
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
lib = root / 'ql-application/threadx/interface/custom_app/lib/librws'
|
||||
source = (lib / 'src/rws_socketpriv.c').read_bytes().decode('latin1')
|
||||
receive = source[source.index('rws_bool rws_socket_recv('):].split('/* RT-Thread Team add */', 1)[0]
|
||||
upgrade = source[source.index('void rws_socket_wait_handshake_responce('):].split('void rws_socket_send_disconnect(', 1)[0]
|
||||
harness = r'''
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rws_handshake.h"
|
||||
#define LIBRWS_USING_MBED_TLS
|
||||
#define MBEDTLS_ERR_SSL_WANT_READ -2
|
||||
#define MBEDTLS_ERR_SSL_WANT_WRITE -3
|
||||
#define MBEDTLS_ERR_NET_RECV_FAILED -4
|
||||
#define WSAEWOULDBLOCK 11
|
||||
#define WSAEINPROGRESS 115
|
||||
#define RWS_RECEIVE_BUFF_SIZE 1024
|
||||
#define COMMAND_WAIT_HANDSHAKE_RESPONCE 3
|
||||
#define COMMAND_INFORM_CONNECTED 4
|
||||
#define COMMAND_INFORM_DISCONNECTED 5
|
||||
#define rws_error_code_read_write_socket 4
|
||||
#define rws_error_code_parse_handshake 5
|
||||
#define LOG_E(...) ((void)0)
|
||||
#define LOG_D(...) ((void)0)
|
||||
#define LOG_I(...) ((void)0)
|
||||
typedef int rws_bool;
|
||||
enum { rws_false, rws_true };
|
||||
typedef struct { int ssl_ctx; } tls;
|
||||
typedef struct {
|
||||
const char *scheme, *expected_accept;
|
||||
tls *ssl;
|
||||
char *payload_buff, *received;
|
||||
size_t received_size, received_len;
|
||||
int socket, command, is_connected;
|
||||
const char *error;
|
||||
} _rws_socket;
|
||||
static int replies[16], reply_count, calls, closes;
|
||||
static size_t offset;
|
||||
static unsigned int ticks;
|
||||
static const char response[] =
|
||||
"HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\n"
|
||||
"Connection: Upgrade\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\nDATA";
|
||||
static unsigned int ql_rtos_get_systicks(void) { return ticks; }
|
||||
static void rws_thread_sleep(int ms) { ticks += (unsigned int)ms; }
|
||||
static void rws_error_delete_clean(const char **e) { *e = NULL; }
|
||||
static const char *rws_error_new_code_descr(int code, const char *text) { (void)code; return text; }
|
||||
static void rws_socket_close(_rws_socket *s) { (void)s; ++closes; }
|
||||
static void rws_socket_resize_received(_rws_socket *s, size_t size) {
|
||||
s->received = (char *)realloc(s->received, size);
|
||||
assert(s->received); s->received_size = size;
|
||||
}
|
||||
static int recv(int fd, char *buf, int size, int flags) {
|
||||
(void)fd; (void)buf; (void)size; (void)flags;
|
||||
assert(0 && "WSS must use TLS receive"); return -1;
|
||||
}
|
||||
static int mbedtls_ssl_read(int *ctx, unsigned char *buf, size_t size) {
|
||||
int ret = calls < reply_count ? replies[calls] : MBEDTLS_ERR_SSL_WANT_READ;
|
||||
(void)ctx; ++calls;
|
||||
if (ret > 0) {
|
||||
assert((size_t)ret <= size && offset + (size_t)ret <= sizeof(response) - 1);
|
||||
memcpy(buf, response + offset, (size_t)ret); offset += (size_t)ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
'''
|
||||
harness += receive + upgrade
|
||||
harness += r'''
|
||||
static void reset(_rws_socket *s, tls *ctx) {
|
||||
free(s->received); memset(s, 0, sizeof(*s));
|
||||
s->scheme = "wss"; s->ssl = ctx;
|
||||
s->expected_accept = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=";
|
||||
s->payload_buff = (char *)malloc(RWS_RECEIVE_BUFF_SIZE); assert(s->payload_buff);
|
||||
s->command = COMMAND_WAIT_HANDSHAKE_RESPONCE;
|
||||
calls = closes = reply_count = 0; offset = 0; ticks = 0;
|
||||
}
|
||||
int main(void) {
|
||||
tls ctx = {0}; _rws_socket s = {0}; int want;
|
||||
for (want = -2; want >= -3; --want) {
|
||||
reset(&s, &ctx); replies[0] = want; reply_count = 1;
|
||||
assert(!rws_socket_recv(&s));
|
||||
assert(!s.error && s.command == COMMAND_WAIT_HANDSHAKE_RESPONCE && closes == 0);
|
||||
replies[1] = 17; replies[2] = want; replies[3] = (int)sizeof(response) - 1 - 17;
|
||||
reply_count = 4;
|
||||
rws_socket_wait_handshake_responce(&s);
|
||||
assert(s.is_connected && !s.error && s.command == COMMAND_INFORM_CONNECTED);
|
||||
assert(calls == 4 && closes == 0 && s.received_len == 4);
|
||||
assert(!memcmp(s.received, "DATA", 4)); free(s.payload_buff);
|
||||
}
|
||||
reset(&s, &ctx);
|
||||
rws_socket_wait_handshake_responce(&s);
|
||||
assert(!s.is_connected && s.error && closes == 1 && ticks >= 2000 && calls < 300);
|
||||
free(s.payload_buff);
|
||||
reset(&s, &ctx); ticks = (unsigned int)-1000;
|
||||
rws_socket_wait_handshake_responce(&s);
|
||||
assert(!s.is_connected && s.error && closes == 1 && calls < 300); free(s.payload_buff);
|
||||
for (want = 0; want >= -99; want -= 99) {
|
||||
reset(&s, &ctx); replies[0] = want; reply_count = 1;
|
||||
rws_socket_wait_handshake_responce(&s);
|
||||
assert(!s.is_connected && s.error && closes == 1 && calls == 1);
|
||||
assert(s.command == COMMAND_INFORM_DISCONNECTED); free(s.payload_buff);
|
||||
}
|
||||
reset(&s, NULL); rws_socket_wait_handshake_responce(&s);
|
||||
assert(s.error && closes == 1 && calls == 0); free(s.payload_buff);
|
||||
reset(&s, &ctx); s.expected_accept = "wrong";
|
||||
replies[0] = (int)sizeof(response) - 1; reply_count = 1;
|
||||
rws_socket_wait_handshake_responce(&s);
|
||||
assert(!s.is_connected && s.error && closes == 1); free(s.payload_buff);
|
||||
free(s.received);
|
||||
puts("PASS: actual TLS receive/upgrade loop: WANT_READ/WRITE, split HTTP 101, trailing frame bytes, timeout/wrap, EOF/fatal, null TLS, invalid Accept");
|
||||
return 0;
|
||||
}
|
||||
'''
|
||||
output = root / 'artifacts/wss'
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
cfile = output / 'test_wss_receive.c'
|
||||
cfile.write_text(harness, encoding='utf-8')
|
||||
exe = output / 'test_wss_receive.exe'
|
||||
subprocess.run(['cl', '/nologo', '/W4', '/WX', '/wd4018', '/TC',
|
||||
'/I' + str(lib / 'inc'), str(cfile), str(lib / 'src/rws_handshake.c'),
|
||||
'/Fo' + str(output) + '/', '/Fe' + str(exe)], check=True)
|
||||
subprocess.run([str(exe)], check=True)
|
||||
@@ -3,12 +3,14 @@ import hashlib
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
output = root / 'artifacts/wss'
|
||||
package = output / 'EG800AKCN_11LG-legacy-wss.zip'
|
||||
package = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else root / 'artifacts/wss/recv-fix/EG800AKCN_11LG-legacy-wss-recv.zip'
|
||||
output = package.parent
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
objdump = root / 'ql-cross-tool/win32/owtoolchain/gcc-arm-none-eabi/bin/arm-none-eabi-objdump.exe'
|
||||
app = root / 'ql-application/threadx/build/app.elf'
|
||||
symbols = subprocess.check_output([str(objdump.with_name('arm-none-eabi-nm.exe')), str(app)], text=True)
|
||||
@@ -17,9 +19,21 @@ required = ['talkingq_parse_wss_url', 'talkingq_root_ca', 'rws_check_handshake',
|
||||
'mbedtls_ctr_drbg_random', 'mbedtls_sha1', 'mbedtls_base64_encode']
|
||||
for symbol in required:
|
||||
assert re.search(r'\b' + symbol + r'$', symbols, re.M), 'Missing linked symbol: ' + symbol
|
||||
kernel_symbols = subprocess.check_output([str(objdump.with_name('arm-none-eabi-nm.exe')),
|
||||
str(root / 'ql-kernel/threadx/build/kernel.axf')], text=True)
|
||||
kernel_required = ['ecdsa_verify_restartable', 'mbedtls_ecdsa_read_signature',
|
||||
'mbedtls_gcm_crypt_and_tag', 'mbedtls_x509_time_is_future',
|
||||
'mbedtls_x509_time_is_past', 'mbedtls_platform_gmtime_r', 'mbedtls_time']
|
||||
for symbol in kernel_required:
|
||||
assert re.search(r'\b' + symbol + r'$', kernel_symbols, re.M), 'Missing kernel capability: ' + symbol
|
||||
clock_body = subprocess.check_output([str(objdump), '-d', '--disassemble=x509_get_current_time',
|
||||
str(root / 'ql-kernel/threadx/build/kernel.axf')], text=True)
|
||||
assert '<mbedtls_platform_gmtime_r>' in clock_body and '<GetCurrentCompTime>' not in clock_body
|
||||
(output / 'x509-clock.disasm.txt').write_text(clock_body)
|
||||
report = {'package': package.name, 'sha256': hashlib.sha256(package.read_bytes()).hexdigest(),
|
||||
'linked_symbols': required, 'hardware_test': 'Not performed',
|
||||
'backend': '443 /ws returns HTTP 404; 8080 is plaintext WS'}
|
||||
'linked_symbols': required, 'kernel_symbols': kernel_required,
|
||||
'hardware_test': '2026-09-16 14:06 device log: ECC/RTC TLS verification passed; receive retry fix awaits device test',
|
||||
'backend': '2026-09-16 11:32 CST: WSS 443 /ws HTTP 101; 8080 plaintext WS'}
|
||||
with zipfile.ZipFile(package) as archive:
|
||||
assert archive.testzip() is None, 'ZIP CRC failure'
|
||||
for name, source in {'cp.bin': 'ql-kernel/threadx/build/release_kernel.bin',
|
||||
@@ -29,9 +43,6 @@ with zipfile.ZipFile(package) as archive:
|
||||
report[name] = {'bytes': len(data), 'sha256': hashlib.sha256(data).hexdigest()}
|
||||
assert b'wss://banban.api.talkingq.com:443/ws' in archive.read('customer_app.bin')
|
||||
report['download_manifest'] = json.loads(archive.read('download.json'))
|
||||
with zipfile.ZipFile(root / 'artifacts/legacy-no-gnss/EG800AKCN_11LG-legacy-no-gnss.zip') as old:
|
||||
with zipfile.ZipFile(package) as new:
|
||||
assert old.read('cp.bin') == new.read('cp.bin'), 'Legacy kernel changed unexpectedly'
|
||||
printf_address = int(re.search(r'^([0-9a-fA-F]+) T printf$', symbols, re.M).group(1), 16)
|
||||
for symbol, binary, expected in [
|
||||
('quec_get_gnssid_task', root / 'ql-kernel/threadx/build/kernel.axf', '<RTI_LOG>'),
|
||||
@@ -40,7 +51,7 @@ for symbol, binary, expected in [
|
||||
body = subprocess.check_output([str(objdump), '-d', '--disassemble=' + symbol, str(binary)], text=True)
|
||||
assert '<' + symbol + '>:' in body and expected in body and 'task_create' not in body
|
||||
(output / (symbol + '.disasm.txt')).write_text(body)
|
||||
report['verification'] = 'PASS: ZIP CRC, current APP/kernel identity, unchanged legacy kernel, GNSS bypass, WSS URL and TLS symbols'
|
||||
report['verification'] = 'PASS: ZIP CRC, current APP/kernel identity, GNSS bypass, WSS URL, ECDSA/GCM/RTC kernel symbols'
|
||||
(output / 'verification.json').write_text(json.dumps(report, indent=2))
|
||||
print(report['verification'])
|
||||
print('SHA256:', report['sha256'])
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
void CPUartLogPrintf(const char *format, ...);
|
||||
@@ -0,0 +1,7 @@
|
||||
/* Host adapter: crypto/X.509 features are the firmware's shared profile.
|
||||
* Only CPU assembly and the OS allocator/clock implementation differ. */
|
||||
#include "../ql-config/config/talkingq_mbedtls_config.h"
|
||||
#undef MBEDTLS_HAVE_ASM
|
||||
#undef MBEDTLS_FS_IO
|
||||
#define QUECTEL_MBEDTLS_SUPPORT
|
||||
#include "mbedtls/check_config.h"
|
||||
Reference in New Issue
Block a user