2019-10-07 3:17 PM
Hi,
I am new the the development and I have been testing the hardware aes module.
I have tested against a known vector and the results differ from what is expected, I have checked the test vectors using AES provider in .NET and I get the results I expect, so am wondering what is wrong with the code I have.
I am running it on a nucleo with the STM32WB55RGV6 MCU
The code is
#include "main.h"
#define AES_TEXT_SIZE 4
/*TEST VECTORS FROM
*https://github.com/ircmaxell/quality-checker/blob/master/tmp/gh_18/PHP-PasswordLib-master/test/Data/Vectors/aes-cbc.test-vectors
*Set 3 vector 3
**/
CRYP_HandleTypeDef hcryp1;
DMA_HandleTypeDef hdma_aes1_in;
DMA_HandleTypeDef hdma_aes1_out;
uint32_t aAES256key[8] =
{283852128,3195128341,4037964587,2172091781,120337695,3607650619,2735773741,4108260361};
/* Initialization vector */
uint32_t AESIV[4] =
{2521758876,2374032254,2071437159, 2100064454};
uint32_t aPlaintextCBC[AES_TEXT_SIZE] =
{ 1176291376,300178595,432143333,4015131162 };
uint32_t aEncryptedtextCBC256[AES_TEXT_SIZE] =
{1765012025,3485129129,1675767973,1628709636};
/* Used for storing the encrypted text */
uint32_t aEncryptedtext[AES_TEXT_SIZE];
/* Used for storing the decrypted text */
uint32_t aDecryptedtext[AES_TEXT_SIZE];
void SystemClock_Config(void);
static void MX_DMA_Init(void);
void SystemClock_Config(void);
void data_cmp(uint32_t *EncryptedText, uint32_t *RefText, uint8_t Size);
/* Private functions ---------------------------------------------------------*/
#if defined(__GNUC__)
extern void initialise_monitor_handles(void);
#endif
int main(void)
{
/* USER CODE BEGIN 1 */
#if defined(__GNUC__)
initialise_monitor_handles();
#endif
HAL_Init();
SystemClock_Config();
MX_DMA_Init();
hcryp1.Instance = AES1;
hcryp1.Init.DataType = CRYP_DATATYPE_8B;
hcryp1.Init.Algorithm = CRYP_AES_CBC;
hcryp1.Init.KeySize = CRYP_KEYSIZE_256B;
hcryp1.Init.pKey = aAES256key;
hcryp1.Init.pInitVect = AESIV;
if(HAL_CRYP_Init(&hcryp1) != HAL_OK)
{
Error_Handler();
}
if (HAL_CRYP_Encrypt_IT(&hcryp1, aPlaintextCBC, AES_TEXT_SIZE, aEncryptedtext)!= HAL_OK)
{
Error_Handler();
}
/* Wait for processing to be done */
while (HAL_CRYP_GetState(&hcryp1) != HAL_CRYP_STATE_READY);
data_cmp(aEncryptedtext, aEncryptedtextCBC256, AES_TEXT_SIZE);
while (1){}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 32;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV5;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4|RCC_CLOCKTYPE_HCLK2
|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV2;
RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
}
static void MX_DMA_Init(void)
{
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
}
void data_cmp(uint32_t *EncryptedText, uint32_t *RefText, uint8_t Size)
{
if(memcmp(EncryptedText, RefText, Size*4) != 0)
{
Error_Handler();
}
else
{
/* Right encryption */
}
}
void Error_Handler(void)
{
printf("\n\r Error Detected...\n ");
while (1)
{
}
}The result return is
{1057025506,4094683968,291643854,3202963458}
Not
{1765012025,3485129129,1675767973,1628709636}
as expected
Any help would be much appreciated.
2019-10-08 1:05 AM
I'm not sure how did you manage to convert those test vectors to uint32_t arrays and why would you do that? Those are binary data represented as hexadecimal values, use uint8_t arrays to represent single bytes. Yeah, you can convert them to uint32_t arrays (and have also endianness and other issues), but why?
So for example, the 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 aes-256 key should become:
uint8_t aes_key[] = {0x60, 0x3d, 0xeb, ...etc};
2019-10-08 1:18 AM
Thank you for your reply @After Forever .
HAL_CRYP_Encrypt_IT requires the key to be uint32t*.
So, for testing, I took the hexadecimal string in a .net console application for test, converted it to bytes (as .net requires the key to be a byte array), executed the test to get the results.
I then used the byte array converted to uint32_t array on the STM32 to replicate the test and I get different results.
So if I have missed something here, would your uint8_t array converted it to uint32_t array give you a different result than that I gave in my example code?
Thanks again
2019-10-08 3:34 AM
Uh, you are right, I haven't used stm32 hardware crypto directly (only through X-CUBE-CRYPTOLIB), and it seems it prefers to work with 32-bit values. Yeah, that's logical, at the low level the values must be copied to/from hardware registers which are 32-bit..
So I would recheck the correctness of your test vectors conversion. There might be endianness issues.
2019-10-08 4:47 AM
Please have a look at CBC256 encryption examples available in ~STM32Cube_FW_WB_V1.3.0\Projects\P-NUCLEO-WB55.Nucleo\Examples\CRYP\CRYP_AESModes
Take care about the endianness and the (8B, 32B) data type.
2019-10-08 3:10 PM
@Remi QUINTIN
Thank you, I was using the examples but I was having trouble replicating the results between the MCU and a .NET application.
I have managed to match the results now and I thought I would share for comments just in case it is a false positive.
So when converting the key and iv from the uint8_t array from .net application to the mcu version, I was converting the array to uint32_t (little endian) to pass to the function for encryption. this fails.
What I have found is that if the key and the iv are converting from uint8_t to uint32_t (big endian) whilst keeping the data little endian the encryption succeeds.
I am not sure this seems right but it works.
Thank you all for the time to view and provide feedback so far, it is much appreciated
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.