Я работаю над переносом приложения, работающего на Arduino Mega
в LPC824
, Следующий фрагмент кода работает по-разному для обеих платформ.
/**
* Calculation of CMAC
*/
void cmac(const uint8_t* data, uint8_t dataLength) {
uint8_t trailer[1] = {0x80};
uint8_t bytes[_lenRnd];
uint8_t temp[_lenRnd];
memcpy(temp, data, dataLength);
concatArray(temp, dataLength, trailer, 1);
dataLength ++;
addPadding(temp, dataLength);
memcpy(bytes, _sk2, _lenRnd);
xorBytes(bytes,temp,_lenRnd);
aes128_ctx_t ctx;
aes128_init(_sessionkey, &ctx);
uint8_t* chain = aes128_enc_sendMode(bytes, _lenRnd, &ctx, _ivect);
Board_UARTPutSTR("chain\n\r");
printBytes(chain, 16, true);
memcpy(_ivect, chain, _lenRnd);
//memcpy(_ivect, aes128_enc_sendMode(bytes,_lenRnd,&ctx,_ivect), _lenRnd);
memcpy(_cmac,_ivect, _lenRnd);
Board_UARTPutSTR("Initialization vector\n\r");
printBytes(_ivect, 16, true);
}
Я ожидаю, что значение как {0x5d, 0xa8, 0x0f, 0x1f, 0x1c, 0x03, 0x7f, 0x16, 0x7e, 0xe5, 0xfd, 0xf3, 0x45, 0xb7, 0x73, 0xa2}
для chain
переменная. Но следующая функция работает по-другому. Печать внутри функции имеет правильное значение, которое я хочу ({5d, 0xa8, 0x0f, 0x1f, 0x1c, 0x03, 0x7f, 0x16, 0x7e, 0xe5, 0xfd, 0xf3, 0x45, 0xb7, 0x73, 0xa2})
,
Но когда функция возвращается chain
имеет другое значение, по сравнению с тем, что я ожидаю, я получаю следующее значение для chain
{0x00, 0x20, 0x00, 0x10, 0x03, 0x01, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00}
Внутри функции результат правильный. Но он возвращает неправильное значение функции, которая его вызвала. Почему так происходит?
uint8_t* aes128_enc_sendMode(unsigned char* data, unsigned short len, aes128_ctx_t* key,
const unsigned char* iv) {
unsigned char tmp[16];
uint8_t chain[16];
unsigned char c;
unsigned char i;
memcpy(chain, iv, 16);
while (len >= 16) {
memcpy(tmp, data, 16);
//xorBytes(tmp,chain,16);
for (i = 0; i < 16; i++) {
tmp[i] = tmp[i] ^ chain[i];
}
aes128_enc(tmp, key);
for (i = 0; i < 16; i++) {
//c = data[i];
data[i] = tmp[i];
chain[i] = tmp[i];
}
len -= 16;
data += 16;
}
Board_UARTPutSTR("Chain!!!:");
printBytes(chain, 16, true);
return chain;
}
Хорошее начало с такой проблемы — удалить как можно больше при воспроизведении ошибки, с минимальным примером кода, ответ обычно ясен. Я сделал это для вас здесь.
uint8_t* aes128_enc_sendMode(void) {
uint8_t chain[16];
return chain;
}
Цепная переменная является локальной для функции, она перестает быть определенной, когда функция существует. Доступ к указателю на эту переменную вызывает неопределенное поведение, не делайте этого.
На практике указатель на массив все еще существует и указывает на произвольный блок памяти. Этот блок памяти больше не зарезервирован и может быть перезаписан в любое время.
Я подозреваю, что это работает для AVR, потому что это простая 8-битная микросхема, и к тому моменту, когда вы ее использовали, этот кусочек памяти оставался беспрепятственным. ARM использовал бы большую оптимизацию, возможно, запустив полный массив в регистрах, чтобы данные не переживали переход.
tldr; Вам нужно malloc () для любых массивов, которые вы хотите прожить после выхода из функции. Будьте осторожны, malloc и встроенные системы идут вместе, как дизель и пенополистирол, они очень быстро запутываются.
Других решений пока нет …