Skip to content

Commit abb0bbc

Browse files
committed
docs: update CRC integrity audit with final results
- Restructure as before/after report showing all fixes applied - Document read request CRC and patch/tpatch/dpatch CRC coverage - List all 8 test cases covering the enhanced CRC scheme - Record cleaned-up unused argparse parameters (entry, args)
1 parent 4bb1b50 commit abb0bbc

1 file changed

Lines changed: 57 additions & 52 deletions

File tree

Tools/WebServer/docs/CRC_Integrity_Audit.md

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,101 +3,106 @@
33
> 日期: 2026-03-10
44
> 范围: `fl.c` (固件) + `serial_protocol.py` (上位机)
55
6-
## 1. 现状分析
6+
## 1. 整改前现状
77

88
### 1.1 CRC 算法
99

1010
两端使用相同的 **CRC-16-CCITT**(初始值 `0xFFFF`,查表法),表一致,算法正确。
1111

1212
固件端 `calc_crc16_base(crc, data, len)` 支持增量计算(链式调用),可以避免拼接 buffer 的二次拷贝。
1313

14-
### 1.2 各命令 CRC 覆盖范围
14+
上位机端新增 `crc16_update(crc, data)` 对应固件端的链式调用。
1515

16-
| 命令 | `addr`/`offset` | `len` | `data` payload | CRC 方向 | 风险 |
17-
|------|:---:|:---:|:---:|:---:|:---:|
18-
| `write` || 隐含 || 上→下 | **** — 地址错误静默写坏内存 |
19-
| `upload` || 隐含 || 上→下 | **** — 偏移错误写坏 alloc buffer |
20-
| `read` (响应) |||| 下→上 | **** — 无法确认数据来自请求地址 |
21-
| `fwrite` | N/A | 隐含 || 上→下 | 低 — 顺序写入,无地址参数 |
22-
| `fread` (响应) | N/A ||| 下→上 | 低 — 顺序读取 |
16+
### 1.2 整改前各命令 CRC 覆盖范围
2317

24-
**核心漏洞**: `--addr` / `-a` (offset) / `--len` 等数值参数未参与 CRC 校验。串口传输中任何一个字符翻转(如 `0x20000000` 变成 `0x20000800`)都不会被检测到。
18+
| 命令 | `addr`/`offset` | `len` | `comp` | `orig` | `target` | `data` | CRC 方向 | 风险 |
19+
|------|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
20+
| `write` || 隐含 ||||| 上→下 | **** — 地址错误静默写坏内存 |
21+
| `upload` || 隐含 ||||| 上→下 | **** — 偏移错误写坏 alloc buffer |
22+
| `read` (请求) ||||||| 上→下 | **** — 地址错误触发 HardFault |
23+
| `read` (响应) ||||||| 下→上 | **** — 无法确认数据来自请求地址 |
24+
| `patch` ||||||| 上→下 | **极高** — 地址错误改变代码跳转 |
25+
| `tpatch` ||||||| 上→下 | **极高** — 同上 |
26+
| `dpatch` ||||||| 上→下 | **极高** — 同上 |
27+
| `fwrite` | N/A | 隐含 ||||| 上→下 | 低 — 顺序写入,无地址参数 |
28+
| `fread` (响应) | N/A |||||| 下→上 | 低 — 顺序读取 |
2529

26-
### 1.3 未使用的 argparse 参数
30+
### 1.3 已清理的未使用 argparse 参数
2731

28-
| 参数 | 声明 | 状态 |
32+
| 参数 | 原声明 | 状态 |
2933
|------|------|------|
30-
| `entry` (`-e`) | `OPT_INTEGER('e', "entry", &entry, "Entry offset")` | **完全未使用** — 无任何命令读取 |
31-
| `args` | `OPT_STRING(0, "args", &args, "Arguments")` | **完全未使用** — 无任何命令读取 |
32-
33-
这两个参数是历史遗留,应当清理以减少攻击面和代码噪音。
34-
35-
### 1.4 命令风格不一致
36-
37-
Python 端 `upload` 使用短选项 (`-a`, `-d`, `-r`),而 `read_memory`/`write_memory` 使用长选项 (`--addr`, `--data`, `--crc`)。功能等价但风格混用,不影响正确性。
34+
| `entry` (`-e`) | `OPT_INTEGER('e', "entry", &entry, "Entry offset")` | 已删除 — 无任何命令使用 |
35+
| `args` | `OPT_STRING(0, "args", &args, "Arguments")` | 已删除 — 无任何命令使用 |
3836

3937
## 2. 整改方案
4038

4139
### 2.1 CRC 增强策略
4240

43-
利用 `calc_crc16_base` 的链式调用能力,`addr`/`offset`/`len` 的字节表示依次喂入 CRC 计算,**无需拼接 buffer,无二次循环**
41+
利用 `calc_crc16_base` 的链式调用能力,将数值参数的字节表示依次喂入 CRC 计算,**无需拼接 buffer,无二次循环**
4442

4543
```c
4644
// 固件端示例 (write 命令)
47-
uint16_t crc = 0xFFFF;
4845
uint32_t addr32 = (uint32_t)addr;
4946
uint32_t len32 = (uint32_t)n;
47+
uint16_t crc = 0xFFFF;
5048
crc = calc_crc16_base(crc, &addr32, sizeof(addr32)); // 4 bytes
5149
crc = calc_crc16_base(crc, &len32, sizeof(len32)); // 4 bytes
5250
crc = calc_crc16_base(crc, buf, n); // payload
5351
```
5452

5553
```python
5654
# 上位机示例 (write 命令)
57-
import struct
58-
crc = 0xFFFF
59-
crc = crc16_update(crc, struct.pack('<II', addr, len(chunk)))
55+
crc = crc16_update(0xFFFF, struct.pack('<II', addr, len(chunk)))
6056
crc = crc16_update(crc, chunk)
6157
```
6258

63-
### 2.2 各命令改动清单
59+
### 2.2 字节序约定
6460

65-
| 命令 | 改动 | CRC 输入 (按顺序) |
66-
|------|------|------|
67-
| `write` | 固件 + 上位机 | `addr(4B)` + `len(4B)` + `data` |
68-
| `upload` | 固件 + 上位机 | `offset(4B)` + `len(4B)` + `data` |
69-
| `read` (响应) | 固件 + 上位机 | `addr(4B)` + `len(4B)` + `data` |
70-
| `fwrite` | 不改 | 无地址参数,当前方案足够 |
71-
| `fread` (响应) | 不改 | 无地址参数,当前方案足够 |
61+
CRC 中的数值参数统一使用 **小端序 (little-endian)** 编码,与 ARM Cortex-M 原生字节序一致。固件端直接取内存地址即可,无需额外转换。
7262

73-
### 2.3 字节序约定
74-
75-
CRC 中的 `addr``len` 统一使用 **小端序 (little-endian)** 编码,与 ARM Cortex-M 原生字节序一致。固件端直接取内存地址即可,无需额外转换。
76-
77-
### 2.4 向后兼容
63+
### 2.3 向后兼容
7864

7965
- `crc` 参数仍然可选(`-1` = 不校验),旧版上位机不传 CRC 时固件跳过校验
80-
- 新版上位机传入的 CRC 已包含 addr/len,新版固件用增强算法验证
81-
- **不兼容场景**: 新上位机 + 旧固件 → CRC 不匹配 → 写入失败(安全侧失败,可接受)
66+
- 新版上位机传入的 CRC 已包含所有数值参数,新版固件用增强算法验证
67+
- **不兼容场景**: 新上位机 + 旧固件 → CRC 不匹配 → 操作失败(安全侧失败,可接受)
8268

83-
## 3. 清理项
69+
## 3. 整改结果
8470

85-
| 项目 | 操作 |
86-
|------|------|
87-
| `entry` 参数 |`argparse_option` 和局部变量中删除 |
88-
| `args` 参数 |`argparse_option` 和局部变量中删除 |
71+
### 3.1 各命令 CRC 覆盖范围(整改后)
8972

90-
## 4. 测试计划
73+
| 命令 | CRC 输入 (按顺序) | CRC 方向 | 状态 |
74+
|------|------|:---:|:---:|
75+
| `write` | `addr(4B)` + `len(4B)` + `data` | 上→下 | ✅ 已修复 |
76+
| `upload` | `offset(4B)` + `len(4B)` + `data` | 上→下 | ✅ 已修复 |
77+
| `read` (请求) | `addr(4B)` + `len(4B)` | 上→下 | ✅ 已修复 |
78+
| `read` (响应) | `addr(4B)` + `len(4B)` + `data` | 下→上 | ✅ 已修复 |
79+
| `patch` | `comp(4B)` + `orig(4B)` + `target(4B)` | 上→下 | ✅ 已修复 |
80+
| `tpatch` | `comp(4B)` + `orig(4B)` + `target(4B)` | 上→下 | ✅ 已修复 |
81+
| `dpatch` | `comp(4B)` + `orig(4B)` + `target(4B)` | 上→下 | ✅ 已修复 |
82+
| `fwrite` | `data` | 上→下 | 无需改动 |
83+
| `fread` (响应) | `data` | 下→上 | 无需改动 |
9184

92-
### 4.1 上位机测试 (`test_serial_protocol.py`)
85+
### 3.2 涉及文件
9386

94-
- `TestWriteMemoryCRC`: 验证 write 命令的 CRC 包含 addr + len + data
95-
- `TestUploadCRC`: 验证 upload 命令的 CRC 包含 offset + len + data
96-
- `TestReadResponseCRC`: 验证 read 响应解析时 CRC 包含 addr + len + data
87+
| 文件 | 改动 |
88+
|------|------|
89+
| `App/func_loader/fl.c` | `cmd_read` 增加请求 CRC 校验;新增 `verify_patch_crc()` 供 patch/tpatch/dpatch 使用;清理 `entry`/`args` 参数 |
90+
| `Tools/WebServer/core/serial_protocol.py` | `read_memory` 发送 `--crc`;新增 `_patch_crc()` 供 patch/tpatch/dpatch 使用;`_parse_read_response` 验证 addr+len+data |
91+
| `Tools/WebServer/utils/crc.py` | 新增 `crc16_update(crc, data)` 支持链式计算 |
92+
| `Tools/WebServer/tests/test_serial_protocol.py` | 新增 `TestEnhancedCRC` 测试类,覆盖 write/upload/read/patch/tpatch/dpatch 的 CRC 验证 |
9793

98-
### 4.2 固件测试
94+
### 3.3 测试覆盖
9995

100-
- 由 CI `lower-machine` job 中的固件单元测试覆盖
96+
| 测试 | 验证内容 |
97+
|------|------|
98+
| `test_write_crc_includes_addr_and_len` | write 命令 CRC 包含 addr + len + data |
99+
| `test_upload_crc_includes_offset_and_len` | upload 命令 CRC 包含 offset + len + data |
100+
| `test_read_response_crc_includes_addr_and_len` | read 响应 CRC 包含 addr + len + data;旧格式 CRC 被拒绝 |
101+
| `test_read_cmd_includes_crc` | read 请求发送 --crc 覆盖 addr + len |
102+
| `test_patch_cmd_includes_crc` | patch 命令 CRC 包含 comp + orig + target |
103+
| `test_tpatch_cmd_includes_crc` | tpatch 命令 CRC 包含 comp + orig + target |
104+
| `test_dpatch_cmd_includes_crc` | dpatch 命令 CRC 包含 comp + orig + target |
105+
| `test_crc16_update_chaining` | crc16_update 链式调用等价于 crc16 拼接调用 |
101106

102107
## 5. 影响评估
103108

0 commit comments

Comments
 (0)