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:
cbb
2026-07-30 11:57:51 +08:00
parent 005072b1df
commit f9ae1be120
9 changed files with 161 additions and 111 deletions
-10
View File
@@ -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
+14 -4
View File
@@ -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();
+6
View File
@@ -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();
+23
View File
@@ -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
View File
@@ -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
View File
@@ -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 设置当前底层回包发送函数。
+40 -40
View File
@@ -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
View File
@@ -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 */
+1 -1
View File
@@ -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)