cancel
Showing results for 
Search instead for 
Did you mean: 

Hardware AES 256 CBC Incorrect results

POliv
Associate II

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.

5 REPLIES 5

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};

POliv
Associate II

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

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.

Remi QUINTIN
ST Employee

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.

POliv
Associate II

@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