refactor: 清理遗留死代码(−353 行)
仓库经多轮迭代积累了不少不再被引用的中间件代码。本次以当前前端依赖的
HTTP 端点为基准(/system/status、/logs、/can/send、/spi/send、/ota/upload、
/ota/update、/ota/relay、/restart),移除以下模块的未引用代码:
- main/transport/protocol.{h,cpp}(−257 行)
* 移除 CMD_* / ACK_* 宏(CMD_HANDSHAKE_REQ 等 16 个)
* 移除未引用方法:crc16Modbus、buildFrame、parseFrame、aesEncrypt、
aesDecrypt、sessionEncrypt、sessionDecrypt、generateRandomNonce
* 保留 init / scrambleGenerate / sessionKeyInit / sessionKeyClear
(被 ota_relay 实际调用)
- main/relay/ota_relay.{h,cpp}(−84 行)
* 移除未引用方法:startHandshake、probeBootHandshake、isStructuredAckWithPayload
* 移除未使用枚举值:RELAY_HANDSHAKE_IDLE、RELAY_RECEIVING、RELAY_TRANSFER_DONE
* 移除字段 ota_meta_t.chunk_count 与宏 OTA_META_NVS_KEY
- main/server/wifi_ota.cpp(−255 行)
* 移除 6 个未被前端调用的 HTTP 端点:/health、/wifi/status、/can/status、
/ota/status、/ota/esp32_status、/api/version
* 移除其处理器与路由注册
* 移除 mbedtls/private/sha256.h 直接引用(SHA-256 已委托 Esp32OtaCore)
- main/server/ble_ota.cpp、main/relay/ota_relay.cpp
* 同步移除 chunk_count 引用
This commit is contained in:
+4
-261
@@ -5,7 +5,9 @@
|
||||
*
|
||||
* 加密实现使用 ESP32-C3 硬件 AES 加速器(通过 mbedtls port)
|
||||
*
|
||||
* 所有功能封装为 Protocol 类的静态方法。
|
||||
* 当前保留的接口:init、scrambleGenerate(nonce 生成)、
|
||||
* sessionKeyInit / sessionKeyClear(会话密钥生命周期管理)。
|
||||
* 帧构建、AES-CBC 加解密、CRC16 等中间件代码已移除。
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -29,225 +31,12 @@ void Protocol::init()
|
||||
if (m_initialized) return;
|
||||
|
||||
DEBUG_INFO("PROT", "=== 初始化协议层 ===");
|
||||
DEBUG_INFO("PROT", "协议层功能: CRC16 Modbus + 硬件 AES-128-CBC");
|
||||
DEBUG_INFO("PROT", "协议层功能: nonce 扰码 + 会话密钥管理");
|
||||
|
||||
m_initialized = true;
|
||||
DEBUG_INFO("PROT", "协议层就绪");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CRC16 Modbus(LE,低字节在前)
|
||||
*/
|
||||
uint16_t Protocol::crc16Modbus(const uint8_t *data, size_t len)
|
||||
{
|
||||
uint16_t crc = 0xFFFF;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
crc ^= data[i];
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (crc & 0x0001) {
|
||||
crc = (crc >> 1) ^ 0xA001;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (crc >> 8) | (crc << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 构建 SPI 帧: SOF + CMD + LEN(2LE) + PAYLOAD + CRC16(2LE)
|
||||
*/
|
||||
int Protocol::buildFrame(uint8_t cmd, const uint8_t *payload, size_t len, uint8_t *out_frame)
|
||||
{
|
||||
if (len > FRAME_MAX_PAYLOAD) {
|
||||
DEBUG_ERR("PROT", "Payload 太大: %zu > %d", len, FRAME_MAX_PAYLOAD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t idx = 0;
|
||||
out_frame[idx++] = FRAME_SOF;
|
||||
out_frame[idx++] = cmd;
|
||||
out_frame[idx++] = (uint8_t)(len & 0xFF);
|
||||
out_frame[idx++] = (uint8_t)((len >> 8) & 0xFF);
|
||||
|
||||
if (payload && len > 0) {
|
||||
memcpy(&out_frame[idx], payload, len);
|
||||
idx += len;
|
||||
}
|
||||
|
||||
uint16_t crc = crc16Modbus(out_frame, idx);
|
||||
out_frame[idx++] = (uint8_t)(crc & 0xFF);
|
||||
out_frame[idx++] = (uint8_t)((crc >> 8) & 0xFF);
|
||||
|
||||
DEBUG_DBG("PROT", "帧构建: cmd=0x%02X, len=%zu, crc=0x%04X", cmd, len, crc);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 解析并校验一帧 SPI 协议数据。
|
||||
*/
|
||||
int Protocol::parseFrame(const uint8_t *frame, size_t frame_len,
|
||||
uint8_t *out_cmd, uint8_t *out_payload, size_t *out_len)
|
||||
{
|
||||
if (frame_len < 6) {
|
||||
DEBUG_WARN("PROT", "帧太短: %zu < 6", frame_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t idx = 0;
|
||||
|
||||
if (frame[idx++] != FRAME_SOF) {
|
||||
DEBUG_WARN("PROT", "无效 SOF: 0x%02X (期望 0x%02X)", frame[0], FRAME_SOF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t cmd = frame[idx++];
|
||||
|
||||
size_t payload_len = frame[idx] | (frame[idx + 1] << 8);
|
||||
idx += 2;
|
||||
|
||||
if (payload_len > FRAME_MAX_PAYLOAD) {
|
||||
DEBUG_ERR("PROT", "Payload 长度太大: %zu > %d", payload_len, FRAME_MAX_PAYLOAD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t expected_len = 1 + 1 + 2 + payload_len + 2;
|
||||
if (frame_len < expected_len) {
|
||||
DEBUG_WARN("PROT", "帧太短: %zu < %zu (期望)", frame_len, expected_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t received_crc = frame[idx + payload_len] | (frame[idx + payload_len + 1] << 8);
|
||||
uint16_t calc_crc = crc16Modbus(frame, idx + payload_len);
|
||||
|
||||
if (received_crc != calc_crc) {
|
||||
DEBUG_WARN("PROT", "CRC 不匹配: 收到=0x%04X, 计算=0x%04X", received_crc, calc_crc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_DBG("PROT", "帧解析: cmd=0x%02X, len=%zu, crc=0x%04X OK", cmd, payload_len, calc_crc);
|
||||
|
||||
if (out_payload && out_len) {
|
||||
memcpy(out_payload, &frame[idx], payload_len);
|
||||
*out_len = payload_len;
|
||||
}
|
||||
if (out_cmd) {
|
||||
*out_cmd = cmd;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 使用 AES-128 CBC 对明文进行加密(PKCS#7 填充)。
|
||||
*/
|
||||
int Protocol::aesEncrypt(const uint8_t *plaintext, size_t len,
|
||||
const uint8_t *key, const uint8_t *iv,
|
||||
uint8_t *ciphertext_out)
|
||||
{
|
||||
if (!plaintext || !key || !iv || !ciphertext_out) {
|
||||
DEBUG_ERR("PROT", "AES 加密参数无效");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// PKCS#7 填充
|
||||
size_t padded_len = ((len / 16) + 1) * 16;
|
||||
uint8_t padded[FRAME_MAX_PAYLOAD + 16];
|
||||
if (padded_len > sizeof(padded)) {
|
||||
DEBUG_ERR("PROT", "填充后长度超出缓冲区: %zu", padded_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(padded, plaintext, len);
|
||||
uint8_t pad_val = (uint8_t)(padded_len - len);
|
||||
memset(&padded[len], pad_val, pad_val);
|
||||
|
||||
DEBUG_DBG("PROT", "AES 加密: 明文=%zu 字节, 填充后=%zu 字节", len, padded_len);
|
||||
|
||||
// 硬件 AES-CBC 加密(使用 ESP32-C3 硬件 AES 加速器)
|
||||
esp_aes_context aes_ctx;
|
||||
esp_aes_init(&aes_ctx);
|
||||
|
||||
int ret = esp_aes_setkey(&aes_ctx, key, 128);
|
||||
if (ret != 0) {
|
||||
DEBUG_ERR("PROT", "esp_aes_setkey 失败: %d", ret);
|
||||
esp_aes_free(&aes_ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t iv_copy[16];
|
||||
memcpy(iv_copy, iv, 16);
|
||||
|
||||
ret = esp_aes_crypt_cbc(&aes_ctx, ESP_AES_ENCRYPT, padded_len, iv_copy, padded, ciphertext_out);
|
||||
|
||||
esp_aes_free(&aes_ctx);
|
||||
|
||||
if (ret != 0) {
|
||||
DEBUG_ERR("PROT", "esp_aes_crypt_cbc 加密失败: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_DBG("PROT", "AES 加密成功: %zu -> %zu 字节", len, padded_len);
|
||||
|
||||
return padded_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 使用 AES-128 CBC 对密文进行解密(去除 PKCS#7 填充)。
|
||||
*/
|
||||
int Protocol::aesDecrypt(const uint8_t *ciphertext, size_t len,
|
||||
const uint8_t *key, const uint8_t *iv,
|
||||
uint8_t *plaintext_out)
|
||||
{
|
||||
if (!ciphertext || !key || !iv || !plaintext_out) {
|
||||
DEBUG_ERR("PROT", "AES 解密参数无效");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len % 16 != 0 || len == 0) {
|
||||
DEBUG_ERR("PROT", "Ciphertext 长度无效: %zu (必须为 16 的倍数)", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_DBG("PROT", "AES 解密: 密文=%zu 字节", len);
|
||||
|
||||
// 硬件 AES-CBC 解密(使用 ESP32-C3 硬件 AES 加速器)
|
||||
esp_aes_context aes_ctx;
|
||||
esp_aes_init(&aes_ctx);
|
||||
|
||||
int ret = esp_aes_setkey(&aes_ctx, key, 128);
|
||||
if (ret != 0) {
|
||||
DEBUG_ERR("PROT", "esp_aes_setkey 失败: %d", ret);
|
||||
esp_aes_free(&aes_ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t iv_copy[16];
|
||||
memcpy(iv_copy, iv, 16);
|
||||
|
||||
ret = esp_aes_crypt_cbc(&aes_ctx, ESP_AES_DECRYPT, len, iv_copy, ciphertext, plaintext_out);
|
||||
|
||||
esp_aes_free(&aes_ctx);
|
||||
|
||||
if (ret != 0) {
|
||||
DEBUG_ERR("PROT", "esp_aes_crypt_cbc 解密失败: %d", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 移除 PKCS#7 填充
|
||||
uint8_t pad = plaintext_out[len - 1];
|
||||
if (pad > 16) {
|
||||
DEBUG_ERR("PROT", "无效填充: %d", pad);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t orig_len = len - pad;
|
||||
DEBUG_DBG("PROT", "AES 解密成功: %zu -> %zu 字节 (填充=%d)", len, orig_len, pad);
|
||||
|
||||
return orig_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 根据时间戳、地址和随机种子生成 16 字节 nonce。
|
||||
*/
|
||||
@@ -303,50 +92,4 @@ void Protocol::sessionKeyClear(session_ctx_t *sess)
|
||||
memset(sess->iv, 0, 16);
|
||||
sess->used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 使用会话上下文加密数据。
|
||||
*/
|
||||
int Protocol::sessionEncrypt(session_ctx_t *sess, const uint8_t *in, size_t len, uint8_t *out)
|
||||
{
|
||||
if (!sess || !in || !out) return -1;
|
||||
|
||||
uint8_t iv_copy[16];
|
||||
memcpy(iv_copy, sess->iv, 16);
|
||||
|
||||
int ret = aesEncrypt(in, len, sess->key, iv_copy, out);
|
||||
|
||||
if (ret > 0) {
|
||||
memcpy(sess->iv, &out[ret - 16], 16);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 使用会话上下文解密数据。
|
||||
*/
|
||||
int Protocol::sessionDecrypt(session_ctx_t *sess, const uint8_t *in, size_t len, uint8_t *out)
|
||||
{
|
||||
if (!sess || !in || !out) return -1;
|
||||
|
||||
uint8_t iv_copy[16];
|
||||
memcpy(iv_copy, sess->iv, 16);
|
||||
|
||||
int ret = aesDecrypt(in, len, sess->key, iv_copy, out);
|
||||
|
||||
if (ret > 0) {
|
||||
memcpy(sess->iv, &in[len - 16], 16);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 使用 ESP-IDF 硬件 RNG 生成随机数
|
||||
*/
|
||||
void Protocol::generateRandomNonce(uint8_t *nonce, size_t len)
|
||||
{
|
||||
esp_fill_random(nonce, len);
|
||||
}
|
||||
Reference in New Issue
Block a user