feat(ota): 完善OTA会话管理机制并优化AES实现
完善OTA会话状态管理,增加clearOtaSessionQueues函数统一处理会话清理, 确保CANCEL/超时/错误情况下完全复位状态、缓冲区和信用额度。 修复bootloader在stay_in_ota模式下的死循环问题,添加活动状态监控, 当OTA会话结束后自动跳转回APP,避免设备永久停留在bootloader。 统一AES模块的数据类型定义,从u8改为标准uint8_t,提升代码兼容性。 更新AES实现中的变量声明,使用一致的uint8_t类型避免潜在类型转换问题。
This commit is contained in:
@@ -1,14 +1,4 @@
|
||||
cbuild-pack:
|
||||
resolved-packs:
|
||||
- resolved-pack: ARM::CMSIS@6.1.0
|
||||
selected-by-pack:
|
||||
- ARM::CMSIS
|
||||
- resolved-pack: ARM::CMSIS-DSP@1.16.2
|
||||
selected-by-pack:
|
||||
- ARM::CMSIS-DSP
|
||||
- resolved-pack: ARM::CMSIS-NN@4.1.0
|
||||
selected-by-pack:
|
||||
- ARM::CMSIS-NN
|
||||
- resolved-pack: GigaDevice::GD32E50x_DFP@1.9.0
|
||||
selected-by-pack:
|
||||
- GigaDevice::GD32E50x_DFP
|
||||
|
||||
@@ -442,10 +442,7 @@ void SpiOta::isrProcessFrame() {
|
||||
s_hasCachedResp = true;
|
||||
}
|
||||
if (s_otaHandler != nullptr) { s_otaHandler->resetToIdle(); }
|
||||
s_otaSessionActive = false;
|
||||
s_otaDataWi = 0U;
|
||||
s_otaDataRi = 0U;
|
||||
s_otaDataCnt = 0U;
|
||||
/* resetToIdle 已 clearOtaSessionQueues;此处再清 RX 流边界 */
|
||||
s_rxStreamLen = 0U;
|
||||
return;
|
||||
}
|
||||
@@ -752,6 +749,18 @@ void SpiOta::configureExti() {
|
||||
nvic_irq_enable(EXTI10_15_IRQn, 1U, 1U);
|
||||
}
|
||||
|
||||
void SpiOta::clearOtaSessionQueues() {
|
||||
/* ISR 与主循环都可能碰 DATA 队列/CREDIT,关中断做原子清理。 */
|
||||
uint32_t primask = enterCritical();
|
||||
s_otaDataWi = 0U;
|
||||
s_otaDataRi = 0U;
|
||||
s_otaDataCnt = 0U;
|
||||
s_otaSessionActive = false;
|
||||
/* 恢复 CREDIT,避免失败后 CREDIT=0 卡住后续握手/重传。 */
|
||||
g_localCredit = CONFIG_OTA_FLASH_BUF_SLOTS;
|
||||
exitCritical(primask);
|
||||
}
|
||||
|
||||
void SpiOta::init() {
|
||||
s_csActive = false;
|
||||
s_rxStreamLen = 0U;
|
||||
@@ -773,6 +782,7 @@ void SpiOta::init() {
|
||||
s_otaDataWi = 0U;
|
||||
s_otaDataRi = 0U;
|
||||
s_otaDataCnt = 0U;
|
||||
g_localCredit = CONFIG_OTA_FLASH_BUF_SLOTS;
|
||||
configureGpio();
|
||||
configureDma();
|
||||
configureSpi0();
|
||||
|
||||
@@ -79,6 +79,12 @@ public:
|
||||
/** @brief ISR DATA 队列中待处理包数(供 OTA.cpp 计算 CREDIT 用)。 */
|
||||
static u8 pendingDataCount();
|
||||
|
||||
/**
|
||||
* @brief OTA 会话完整复位(CANCEL / resetToIdle / 进 BOOT 共用)。
|
||||
* 清空 ISR DATA 队列、会话标志,并恢复 g_localCredit。
|
||||
*/
|
||||
static void clearOtaSessionQueues();
|
||||
|
||||
/** @brief 主循环入队 TX 后装载 DMA + 更新 DATA_READY(擦除中途刷 WAIT 用)。 */
|
||||
static void servicePendingTx();
|
||||
|
||||
|
||||
@@ -248,10 +248,33 @@ void BootloaderSystem::run() {
|
||||
#if DEBUG_PRINT
|
||||
printf("[BOOT] path=stay_in_ota\r\n");
|
||||
#endif
|
||||
/* stay_in_ota 期间若 OTA 会话结束(被 CANCEL 或超时回 IDLE),
|
||||
* 必须主动跳回 APP,否则电机会永久停在 Bootloader,
|
||||
* 表现为取消 OTA 后 CAN 业务帧再无 ACK、整条总线"通信不通"。
|
||||
* 旧实现是 while(1) 无退出条件,且 OTA.cpp 的 CANCEL 分支只置 IDLE
|
||||
* 不跳 APP,连 OTA_TIMEOUT 兜底也因 ota_time 不再累加而失效。 */
|
||||
uint32_t hb_ota = 0U;
|
||||
uint32_t idle_since = 0U;
|
||||
bool was_active = false;
|
||||
while (1) {
|
||||
pollAllLinks();
|
||||
heartbeatPrint(hb_ota, 1U, "stay_in_ota");
|
||||
|
||||
const bool active_now = ota.isActive();
|
||||
if (active_now) {
|
||||
was_active = true;
|
||||
idle_since = 0U;
|
||||
} else if (was_active) {
|
||||
/* 曾进入 OTA,现在回到 IDLE(CANCEL/超时/完成)→ 跳回 APP */
|
||||
#if DEBUG_PRINT
|
||||
printf("[BOOT] stay_in_ota -> ota ended, jump app\r\n");
|
||||
#endif
|
||||
if (verifyAppCrc(APPLATEST_START_ADDR)) {
|
||||
ota.jumpToApplication();
|
||||
}
|
||||
/* jumpToApplication 失败(CRC/向量不合法)则留在 BOOT */
|
||||
was_active = false;
|
||||
}
|
||||
delay_1ms(1);
|
||||
}
|
||||
} else {
|
||||
|
||||
+47
-15
@@ -256,6 +256,30 @@ static inline void send_structured_ack(uint32_t seq_or_flag) {
|
||||
*
|
||||
* @return 无。
|
||||
*/
|
||||
/**
|
||||
* @brief 完整复位 OTA 会话到 IDLE(密钥/缓冲/CREDIT/SPI 队列一并清理)。
|
||||
*/
|
||||
void OTAHandler::resetToIdle() {
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
ota_time = 0;
|
||||
ota_error = OTA_ERROR_NONE;
|
||||
received_size = 0;
|
||||
expected_size = 0;
|
||||
memset(current_K_session, 0, sizeof(current_K_session));
|
||||
memset(nonce_server, 0, sizeof(nonce_server));
|
||||
memset(&aes_ctx, 0, sizeof(aes_ctx));
|
||||
pending_flash_erase = false;
|
||||
pending_app_jump = false;
|
||||
pending_finish_ack = false;
|
||||
pending_finish_ota = false;
|
||||
flash_buf_wi = 0U;
|
||||
flash_buf_ri = 0U;
|
||||
flash_buf_cnt = 0U;
|
||||
next_expected_packet = 0U;
|
||||
/* SPI 侧:清 ISR DATA 队列 + 恢复 g_localCredit,避免失败后半会话残留 */
|
||||
SpiOta::clearOtaSessionQueues();
|
||||
}
|
||||
|
||||
void OTAHandler::init() {
|
||||
/** 默认回包出口先绑定到 CAN。 */
|
||||
transport_send = ota_can_sender;
|
||||
@@ -341,8 +365,8 @@ void OTAHandler::process() {
|
||||
pending_finish_ota = false;
|
||||
|
||||
if (!validateApplication()) {
|
||||
resetToIdle();
|
||||
ota_error = OTA_ERROR_FLASH_ERROR;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(0xFFFFFFFFU, OTA_ERROR_FLASH_ERROR);
|
||||
} else {
|
||||
/** 计算并写入 A区固件 CRC32,供后续启动时完整性校验。 */
|
||||
@@ -395,12 +419,11 @@ void OTAHandler::process() {
|
||||
if (ota_time > OTA_TIMEOUT) {
|
||||
/**
|
||||
* OTA 会话超时:
|
||||
* - 复位状态机到空闲态
|
||||
* - 完整复位状态机到空闲态(含 CREDIT/缓冲)
|
||||
* - 上报超时错误
|
||||
* - 如果当前主应用仍有效,则尝试回到主应用运行
|
||||
*/
|
||||
ota_time = 0;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
resetToIdle();
|
||||
ota_error = OTA_ERROR_TIMEOUT;
|
||||
|
||||
volatile u32 *flash_ptr = (volatile u32 *)n_APP_LATEST_CHECK_ADDR;
|
||||
@@ -771,12 +794,21 @@ void OTAHandler::handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len) {
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* CANCEL:无条件终止当前 OTA 会话,回到空闲态。
|
||||
* CANCEL:无条件终止当前 OTA 会话,完整回到空闲态。
|
||||
* 走 resetToIdle():清密钥/缓冲/CREDIT/SPI DATA 队列,避免半会话残留。
|
||||
* 仅置 IDLE 不跳 APP:跳转由 main.cpp stay_in_ota 循环检测 ota.isActive()
|
||||
* 变 false 后统一执行,避免在此处关中断/校验与 ISR 上下文冲突。
|
||||
* 回 ACK 便于 ESP32 确认远端已清理(无 payload 时也 ACK)。
|
||||
*/
|
||||
if (type == OTA_LINK_MSG_CANCEL) {
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
ota_time = 0;
|
||||
ota_error = OTA_ERROR_NONE;
|
||||
resetToIdle();
|
||||
#if DEBUG_PRINT
|
||||
printf("[OTA] CANCEL -> resetToIdle\r\n");
|
||||
#endif
|
||||
{
|
||||
u8 cancel_ack[1] = {0x03U};
|
||||
send_ack_frame(1, cancel_ack);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/**
|
||||
@@ -865,8 +897,8 @@ void OTAHandler::handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len) {
|
||||
} else {
|
||||
u32 offset = receive_packet_num * OTA_PACKET_SIZE;
|
||||
if (offset >= expected_size) {
|
||||
resetToIdle();
|
||||
ota_error = OTA_ERROR_INVALID_SIZE;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(receive_packet_num, OTA_ERROR_INVALID_SIZE);
|
||||
return;
|
||||
}
|
||||
@@ -936,8 +968,8 @@ void OTAHandler::handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len) {
|
||||
received_size = 0;
|
||||
next_expected_packet = 0U;
|
||||
} else {
|
||||
resetToIdle();
|
||||
ota_error = OTA_ERROR_INVALID_SIZE;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(0U, OTA_ERROR_INVALID_SIZE);
|
||||
return;
|
||||
}
|
||||
@@ -964,8 +996,8 @@ void OTAHandler::handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len) {
|
||||
return;
|
||||
}
|
||||
|
||||
resetToIdle();
|
||||
ota_error = OTA_ERROR_INVALID_PACKET;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(0xFFFFFFFFU, OTA_ERROR_INVALID_PACKET);
|
||||
return;
|
||||
}
|
||||
@@ -978,12 +1010,12 @@ void OTAHandler::handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len) {
|
||||
send_wait_frame(1, wait_hint);
|
||||
}
|
||||
else {
|
||||
ota_error = OTA_ERROR_INVALID_PACKET;
|
||||
#if DEBUG_PRINT
|
||||
printf("[OTA] DATA ignored/INV_PKT: type=%u len=%u state=%u\r\n",
|
||||
(unsigned)type, (unsigned)len, (unsigned)ota_state);
|
||||
#endif
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
resetToIdle();
|
||||
ota_error = OTA_ERROR_INVALID_PACKET;
|
||||
send_error_frame(0xFFFFFFFFU, OTA_ERROR_INVALID_PACKET);
|
||||
}
|
||||
}
|
||||
@@ -1050,8 +1082,8 @@ void OTAHandler::handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len) {
|
||||
}
|
||||
|
||||
if (memcmp(plaintext, expected, 16) != 0) {
|
||||
resetToIdle();
|
||||
ota_error = OTA_ERROR_INVALID_KEY;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(0xFFFFFFFFU, OTA_ERROR_INVALID_KEY);
|
||||
return;
|
||||
}
|
||||
@@ -1062,8 +1094,8 @@ void OTAHandler::handleLinkMessage(ota_link_msg_type_t type, u8 *data, u8 len) {
|
||||
}
|
||||
/** 其它情况一律判定为握手非法。 */
|
||||
else {
|
||||
resetToIdle();
|
||||
ota_error = OTA_ERROR_INVALID_HANDSHAKE;
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
send_error_frame(0xFFFFFFFFU, OTA_ERROR_INVALID_HANDSHAKE);
|
||||
return;
|
||||
}
|
||||
|
||||
+5
-21
@@ -84,31 +84,15 @@ class OTAHandler {
|
||||
u8 getState() const { return (u8)ota_state; }
|
||||
|
||||
/**
|
||||
* @brief 重置 OTA 状态机到 IDLE,用于进BOOT命令等场景。
|
||||
* @brief 重置 OTA 状态机到 IDLE(完整清理会话上下文)。
|
||||
*
|
||||
* 上位机发 0xB0 进BOOT命令时,如果设备已在 BOOT 中,
|
||||
* 需要将 OTA 状态机重置为 IDLE,确保后续握手能正常进行。
|
||||
* 用于:0xB0 进 BOOT、SPI/CAN CANCEL、握手/认证失败、会话超时等。
|
||||
* 除状态枚举外,清密钥/缓冲/pending,并恢复 g_localCredit,
|
||||
* 避免失败后卡在 WAITING_* 或 CREDIT=0 导致下次握手异常。
|
||||
*
|
||||
* @return 无。
|
||||
*/
|
||||
void resetToIdle() {
|
||||
ota_state = OTA_STATE_IDLE;
|
||||
ota_time = 0;
|
||||
ota_error = OTA_ERROR_NONE;
|
||||
received_size = 0;
|
||||
expected_size = 0;
|
||||
memset(current_K_session, 0, sizeof(current_K_session));
|
||||
memset(nonce_server, 0, sizeof(nonce_server));
|
||||
memset(&aes_ctx, 0, sizeof(aes_ctx));
|
||||
pending_flash_erase = false;
|
||||
pending_app_jump = false;
|
||||
pending_finish_ack = false;
|
||||
pending_finish_ota = false;
|
||||
flash_buf_wi = 0U;
|
||||
flash_buf_ri = 0U;
|
||||
flash_buf_cnt = 0U;
|
||||
next_expected_packet = 0U;
|
||||
}
|
||||
void resetToIdle();
|
||||
|
||||
/**
|
||||
* @brief 设置当前底层回包发送函数。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "aes128.h"
|
||||
|
||||
/** S盒 (Substitution Box) */
|
||||
static const u8 sbox[256] = {
|
||||
static const uint8_t sbox[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
|
||||
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
||||
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
|
||||
@@ -26,7 +26,7 @@ static const u8 sbox[256] = {
|
||||
0xb0, 0x54, 0xbb, 0x16};
|
||||
|
||||
/** 逆S盒 (InvSBox) */
|
||||
const u8 inv_sbox[256] = {
|
||||
const uint8_t inv_sbox[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
||||
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
|
||||
@@ -51,11 +51,11 @@ const u8 inv_sbox[256] = {
|
||||
0x55, 0x21, 0x0c, 0x7d};
|
||||
|
||||
/** 轮常量 */
|
||||
static const u8 rcon[10] = {0x01, 0x02, 0x04, 0x08, 0x10,
|
||||
static const uint8_t rcon[10] = {0x01, 0x02, 0x04, 0x08, 0x10,
|
||||
0x20, 0x40, 0x80, 0x1b, 0x36};
|
||||
|
||||
/** 伽罗瓦域乘法 (xtime) - 确保正确 */
|
||||
static u8 xtime(u8 x) { return (x << 1) ^ (((x >> 7) & 1) * 0x1b); }
|
||||
static uint8_t xtime(uint8_t x) { return (x << 1) ^ (((x >> 7) & 1) * 0x1b); }
|
||||
|
||||
/** 关键修复:AES状态矩阵是列优先排列! */
|
||||
/** 内存布局应该是:s00, s10, s20, s30, s01, s11, s21, s31, ... */
|
||||
@@ -69,8 +69,8 @@ static u8 xtime(u8 x) { return (x << 1) ^ (((x >> 7) & 1) * 0x1b); }
|
||||
* @param round_key 指向 16 字节轮密钥的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void add_round_key(u8 *state, const u8 *round_key) {
|
||||
for (u8 i = 0; i < 16; i++) {
|
||||
void add_round_key(uint8_t *state, const uint8_t *round_key) {
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
state[i] ^= round_key[i];
|
||||
}
|
||||
}
|
||||
@@ -82,8 +82,8 @@ void add_round_key(u8 *state, const u8 *round_key) {
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void sub_bytes(u8 *state) {
|
||||
for (u8 i = 0; i < 16; i++) {
|
||||
void sub_bytes(uint8_t *state) {
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
state[i] = sbox[state[i]];
|
||||
}
|
||||
}
|
||||
@@ -95,8 +95,8 @@ void sub_bytes(u8 *state) {
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void shift_rows(u8 *state) {
|
||||
u8 temp;
|
||||
void shift_rows(uint8_t *state) {
|
||||
uint8_t temp;
|
||||
|
||||
/** AES状态矩阵(列优先): */
|
||||
/** 列0: state[0], state[1], state[2], state[3] -> 行0,1,2,3 */
|
||||
@@ -135,11 +135,11 @@ void shift_rows(u8 *state) {
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void mix_columns(u8 *state) {
|
||||
u8 a[4], b[4];
|
||||
void mix_columns(uint8_t *state) {
|
||||
uint8_t a[4], b[4];
|
||||
|
||||
/** 处理每一列 */
|
||||
for (u8 col = 0; col < 4; col++) {
|
||||
for (uint8_t col = 0; col < 4; col++) {
|
||||
/** 获取当前列的4个字节 */
|
||||
a[0] = state[col * 4 + 0];
|
||||
a[1] = state[col * 4 + 1];
|
||||
@@ -161,9 +161,9 @@ void mix_columns(u8 *state) {
|
||||
}
|
||||
|
||||
/** 伽罗瓦域乘法 (用于逆列混合) */
|
||||
static u8 gf_mul(u8 a, u8 b) {
|
||||
u8 p = 0;
|
||||
u8 high_bit;
|
||||
static uint8_t gf_mul(uint8_t a, uint8_t b) {
|
||||
uint8_t p = 0;
|
||||
uint8_t high_bit;
|
||||
|
||||
while (b) {
|
||||
if (b & 1) {
|
||||
@@ -186,8 +186,8 @@ static u8 gf_mul(u8 a, u8 b) {
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void inv_sub_bytes(u8 *state) {
|
||||
for (u8 i = 0; i < 16; i++) {
|
||||
void inv_sub_bytes(uint8_t *state) {
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
state[i] = inv_sbox[state[i]];
|
||||
}
|
||||
}
|
||||
@@ -199,8 +199,8 @@ void inv_sub_bytes(u8 *state) {
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void inv_shift_rows(u8 *state) {
|
||||
u8 temp;
|
||||
void inv_shift_rows(uint8_t *state) {
|
||||
uint8_t temp;
|
||||
|
||||
/** 第2行右移1位 */
|
||||
temp = state[13];
|
||||
@@ -232,11 +232,11 @@ void inv_shift_rows(u8 *state) {
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void inv_mix_columns(u8 *state) {
|
||||
u8 a[4], b[4];
|
||||
void inv_mix_columns(uint8_t *state) {
|
||||
uint8_t a[4], b[4];
|
||||
|
||||
/** 处理每一列 */
|
||||
for (u8 col = 0; col < 4; col++) {
|
||||
for (uint8_t col = 0; col < 4; col++) {
|
||||
/** 获取当前列的4个字节 */
|
||||
a[0] = state[col * 4 + 0];
|
||||
a[1] = state[col * 4 + 1];
|
||||
@@ -263,8 +263,8 @@ void inv_mix_columns(u8 *state) {
|
||||
|
||||
/** 密钥扩展 - 修复为标准实现 */
|
||||
static void key_expansion(aes128_context *ctx) {
|
||||
u8 temp[4];
|
||||
u8 i, rcon_iter = 0;
|
||||
uint8_t temp[4];
|
||||
uint8_t i, rcon_iter = 0;
|
||||
|
||||
/** 复制原始密钥到第一轮密钥 */
|
||||
memcpy(ctx->round_keys[0], ctx->key, 16);
|
||||
@@ -278,7 +278,7 @@ static void key_expansion(aes128_context *ctx) {
|
||||
temp[3] = ctx->round_keys[i - 1][15];
|
||||
|
||||
/** 字循环 (RotWord) */
|
||||
u8 t = temp[0];
|
||||
uint8_t t = temp[0];
|
||||
temp[0] = temp[1];
|
||||
temp[1] = temp[2];
|
||||
temp[2] = temp[3];
|
||||
@@ -300,7 +300,7 @@ static void key_expansion(aes128_context *ctx) {
|
||||
ctx->round_keys[i][3] = ctx->round_keys[i - 1][3] ^ temp[3];
|
||||
|
||||
/** 生成其他列 */
|
||||
for (u8 j = 1; j < 4; j++) {
|
||||
for (uint8_t j = 1; j < 4; j++) {
|
||||
ctx->round_keys[i][j * 4 + 0] =
|
||||
ctx->round_keys[i][(j - 1) * 4 + 0] ^
|
||||
ctx->round_keys[i - 1][j * 4 + 0];
|
||||
@@ -324,7 +324,7 @@ static void key_expansion(aes128_context *ctx) {
|
||||
* @param key 指向 16 字节密钥的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_set_key(aes128_context *ctx, const u8 *key) {
|
||||
void aes128_set_key(aes128_context *ctx, const uint8_t *key) {
|
||||
memcpy(ctx->key, key, AES128_KEY_LEN);
|
||||
key_expansion(ctx);
|
||||
}
|
||||
@@ -337,7 +337,7 @@ void aes128_set_key(aes128_context *ctx, const u8 *key) {
|
||||
* @param output 指向输出缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output) {
|
||||
void aes128_encrypt_block(aes128_context *ctx, const uint8_t *input, uint8_t *output) {
|
||||
/** 复制输入到状态 */
|
||||
memcpy(ctx->state, input, AES_BLOCK_SIZE);
|
||||
|
||||
@@ -345,7 +345,7 @@ void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output) {
|
||||
add_round_key(ctx->state, ctx->round_keys[0]);
|
||||
|
||||
/** 9轮标准轮 */
|
||||
for (u8 round = 1; round <= 9; round++) {
|
||||
for (uint8_t round = 1; round <= 9; round++) {
|
||||
sub_bytes(ctx->state);
|
||||
shift_rows(ctx->state);
|
||||
mix_columns(ctx->state);
|
||||
@@ -369,8 +369,8 @@ void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output) {
|
||||
* @param output 指向 48 字节输出缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const u8 *input,
|
||||
u8 *output) {
|
||||
void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const uint8_t *input,
|
||||
uint8_t *output) {
|
||||
/** 分3块加密 (48 = 16 * 3) */
|
||||
aes128_encrypt_block(ctx, input, output);
|
||||
aes128_encrypt_block(ctx, input + 16, output + 16);
|
||||
@@ -385,7 +385,7 @@ void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const u8 *input,
|
||||
* @param output 指向输出缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output) {
|
||||
void aes128_decrypt_block(aes128_context *ctx, const uint8_t *input, uint8_t *output) {
|
||||
/** 复制输入到状态 */
|
||||
memcpy(ctx->state, input, AES_BLOCK_SIZE);
|
||||
|
||||
@@ -393,7 +393,7 @@ void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output) {
|
||||
add_round_key(ctx->state, ctx->round_keys[10]);
|
||||
|
||||
/** 9轮标准解密轮 */
|
||||
for (u8 round = 9; round >= 1; round--) {
|
||||
for (uint8_t round = 9; round >= 1; round--) {
|
||||
inv_shift_rows(ctx->state);
|
||||
inv_sub_bytes(ctx->state);
|
||||
add_round_key(ctx->state, ctx->round_keys[round]);
|
||||
@@ -417,8 +417,8 @@ void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output) {
|
||||
* @param output 指向 48 字节输出缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const u8 *input,
|
||||
u8 *output) {
|
||||
void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const uint8_t *input,
|
||||
uint8_t *output) {
|
||||
/** 分3块解密 (48 = 16 * 3) */
|
||||
aes128_decrypt_block(ctx, input, output);
|
||||
aes128_decrypt_block(ctx, input + 16, output + 16);
|
||||
@@ -434,11 +434,11 @@ void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const u8 *input,
|
||||
* @retval 1 验证成功。
|
||||
* @retval 0 验证失败。
|
||||
*/
|
||||
u8 aes128_verify_encryption(aes128_context *ctx, const u8 *original_data,
|
||||
uint8_t aes128_verify_encryption(aes128_context *ctx, const uint8_t *original_data,
|
||||
size_t length) {
|
||||
u8 temp_ciphertext[48];
|
||||
u8 temp_plaintext[48];
|
||||
u8 result = 1; /**< 1表示验证成功,0表示失败 */
|
||||
uint8_t temp_ciphertext[48];
|
||||
uint8_t temp_plaintext[48];
|
||||
uint8_t result = 1; /**< 1表示验证成功,0表示失败 */
|
||||
|
||||
/** 1. 加密原始数据 */
|
||||
aes128_ecb_encrypt_48bytes(ctx, original_data, temp_ciphertext);
|
||||
|
||||
+25
-20
@@ -1,6 +1,11 @@
|
||||
#ifndef __AES_H
|
||||
#define __AES_H
|
||||
#include "cstdint"
|
||||
|
||||
/**
|
||||
* AES-128 公共头:自包含,不依赖 config.h 的 u8 别名或 include 顺序。
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/** @brief AES-128 密钥长度,单位为字节。 */
|
||||
@@ -13,9 +18,9 @@
|
||||
* @brief AES-128 上下文。
|
||||
*/
|
||||
typedef struct {
|
||||
u8 key[AES128_KEY_LEN]; /**< 原始 128bit 密钥。 */
|
||||
u8 round_keys[11][16]; /**< 扩展后的 11 组轮密钥。 */
|
||||
u8 state[AES_BLOCK_SIZE]; /**< 当前状态矩阵。 */
|
||||
uint8_t key[AES128_KEY_LEN]; /**< 原始 128bit 密钥。 */
|
||||
uint8_t round_keys[11][16]; /**< 扩展后的 11 组轮密钥。 */
|
||||
uint8_t state[AES_BLOCK_SIZE]; /**< 当前状态矩阵。 */
|
||||
} aes128_context;
|
||||
|
||||
/**
|
||||
@@ -25,7 +30,7 @@ typedef struct {
|
||||
* @param round_key 指向 16 字节轮密钥的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void add_round_key(u8 *state, const u8 *round_key);
|
||||
void add_round_key(uint8_t *state, const uint8_t *round_key);
|
||||
|
||||
/**
|
||||
* @brief 对状态矩阵执行 SubBytes 变换。
|
||||
@@ -33,7 +38,7 @@ void add_round_key(u8 *state, const u8 *round_key);
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void sub_bytes(u8 *state);
|
||||
void sub_bytes(uint8_t *state);
|
||||
|
||||
/**
|
||||
* @brief 对状态矩阵执行 ShiftRows 变换。
|
||||
@@ -41,7 +46,7 @@ void sub_bytes(u8 *state);
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void shift_rows(u8 *state);
|
||||
void shift_rows(uint8_t *state);
|
||||
|
||||
/**
|
||||
* @brief 对状态矩阵执行 MixColumns 变换。
|
||||
@@ -49,7 +54,7 @@ void shift_rows(u8 *state);
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void mix_columns(u8 *state);
|
||||
void mix_columns(uint8_t *state);
|
||||
|
||||
/**
|
||||
* @brief 对状态矩阵执行逆字节替换。
|
||||
@@ -57,7 +62,7 @@ void mix_columns(u8 *state);
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void inv_sub_bytes(u8 *state);
|
||||
void inv_sub_bytes(uint8_t *state);
|
||||
|
||||
/**
|
||||
* @brief 对状态矩阵执行逆行移位。
|
||||
@@ -65,7 +70,7 @@ void inv_sub_bytes(u8 *state);
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void inv_shift_rows(u8 *state);
|
||||
void inv_shift_rows(uint8_t *state);
|
||||
|
||||
/**
|
||||
* @brief 对状态矩阵执行逆列混合。
|
||||
@@ -73,7 +78,7 @@ void inv_shift_rows(u8 *state);
|
||||
* @param state 指向 16 字节状态矩阵的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void inv_mix_columns(u8 *state);
|
||||
void inv_mix_columns(uint8_t *state);
|
||||
|
||||
/**
|
||||
* @brief 设置 AES-128 密钥并完成轮密钥扩展。
|
||||
@@ -82,7 +87,7 @@ void inv_mix_columns(u8 *state);
|
||||
* @param key 指向 16 字节密钥的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_set_key(aes128_context *ctx, const u8 *key);
|
||||
void aes128_set_key(aes128_context *ctx, const uint8_t *key);
|
||||
|
||||
/**
|
||||
* @brief 加密单个 16 字节分组。
|
||||
@@ -92,7 +97,7 @@ void aes128_set_key(aes128_context *ctx, const u8 *key);
|
||||
* @param output 指向 16 字节输出缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output);
|
||||
void aes128_encrypt_block(aes128_context *ctx, const uint8_t *input, uint8_t *output);
|
||||
|
||||
/**
|
||||
* @brief 以 ECB 模式加密 48 字节数据。
|
||||
@@ -102,8 +107,8 @@ void aes128_encrypt_block(aes128_context *ctx, const u8 *input, u8 *output);
|
||||
* @param output 指向 48 字节输出缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const u8 *input,
|
||||
u8 *output);
|
||||
void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const uint8_t *input,
|
||||
uint8_t *output);
|
||||
|
||||
/**
|
||||
* @brief 解密单个 16 字节分组。
|
||||
@@ -113,7 +118,7 @@ void aes128_ecb_encrypt_48bytes(aes128_context *ctx, const u8 *input,
|
||||
* @param output 指向 16 字节输出缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output);
|
||||
void aes128_decrypt_block(aes128_context *ctx, const uint8_t *input, uint8_t *output);
|
||||
|
||||
/**
|
||||
* @brief 以 ECB 模式解密 48 字节数据。
|
||||
@@ -123,8 +128,8 @@ void aes128_decrypt_block(aes128_context *ctx, const u8 *input, u8 *output);
|
||||
* @param output 指向 48 字节输出缓冲区的指针。
|
||||
* @return 无。
|
||||
*/
|
||||
void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const u8 *input,
|
||||
u8 *output);
|
||||
void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const uint8_t *input,
|
||||
uint8_t *output);
|
||||
|
||||
/**
|
||||
* @brief 执行 AES 加密-解密自检。
|
||||
@@ -135,10 +140,10 @@ void aes128_ecb_decrypt_48bytes(aes128_context *ctx, const u8 *input,
|
||||
* @retval 1 验证成功。
|
||||
* @retval 0 验证失败。
|
||||
*/
|
||||
u8 aes128_verify_encryption(aes128_context *ctx, const u8 *original_data,
|
||||
uint8_t aes128_verify_encryption(aes128_context *ctx, const uint8_t *original_data,
|
||||
size_t length);
|
||||
|
||||
/** @brief 逆 S 盒查找表。 */
|
||||
extern const u8 inv_sbox[256];
|
||||
extern const uint8_t inv_sbox[256];
|
||||
|
||||
#endif /* __AES_H */
|
||||
|
||||
@@ -16,7 +16,7 @@ typedef uint32_t u32;
|
||||
#define BOOT_FW_VERSION_MAJOR 1U
|
||||
#define BOOT_FW_VERSION_MINOR 1U
|
||||
#define BOOT_FW_VERSION_PATCH 0U
|
||||
#define BOOT_FW_VERSION_BUILD 0U
|
||||
#define BOOT_FW_VERSION_BUILD 1U
|
||||
|
||||
/**
|
||||
* Flash 布局说明(GD32E508VE,512KB)
|
||||
|
||||
Reference in New Issue
Block a user