Closed fermentedfly closed 3 months ago
Hello @fermentedfly,
Thank you for reporting. Would you please clarify your problem do you want to have the ability to changes DataType
into the Key and initialization vector.
Otherwise, you should first call HAL_CRYP_SetConfig
then HAL_CRYP_Init
and then HAL_CRYP_Encrypt
Regards,
I've attached a demo.
testCBCNoSwap()
passes key, IV, and data in big-endian, with DataType
set to CRYP_NO_SWAP
. This is similar to some examples in STM32Cube and works.
testCBCByteSwap()
passes key, IV, and data in little-endian, with DataType
set to CRYP_BYTE_SWAP
. This fails. I've had a look into stm32u5xx_hal_cryp.c
, the cause for the failure is that key and IV are always interpreted as being in big-endian, regardless of DataType
.
testCBCByteSwapKeyIVBigEndian()
passes key and IV in big-endian and data in little-endian, with DataType
set to CRYP_BYTE_SWAP
. This works.
Herein lies the problem: There is no way to pass key and IV in little-endian, which is an issue for my application.
void testCBCNoSwap()
{
__HAL_RCC_AES_CLK_ENABLE();
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/aesmmt.zip
// CBCMMT128.rsp Encrypt Count 0
// CRYP_NO_SWAP
uint32_t key[] = {0x1f8e4973, 0x953f3fb0, 0xbd6b1666, 0x2e9a3c17};
static_assert(sizeof(key) == 16);
uint32_t iv[] = {0x2fe2b333, 0xceda8f98, 0xf4a99b40, 0xd2cd34a8};
static_assert(sizeof(iv) == 16);
uint32_t pt[] = {0x45cf1296, 0x4fc824ab, 0x76616ae2, 0xf4bf0822};
static_assert(sizeof(pt) == 16);
uint32_t ctRef[] = {0x0f61c4d4, 0x4c5147c0, 0x3c195ad7, 0xe2cc12b2};
static_assert(sizeof(ctRef) == 16);
decltype(ctRef) ct{};
CRYP_HandleTypeDef handle{.Instance = AES,
.Init = {
.DataType = CRYP_NO_SWAP,
.KeySize = CRYP_KEYSIZE_128B,
.pKey = (uint32_t *)key,
.pInitVect = (uint32_t *)iv,
.Algorithm = CRYP_AES_CBC,
.DataWidthUnit = CRYP_DATAWIDTHUNIT_WORD,
}};
configASSERT(HAL_CRYP_Init(&handle) == HAL_OK);
configASSERT(HAL_CRYP_Encrypt(&handle, (uint32_t *)pt, std::extent_v<decltype(pt)>, (uint32_t *)ct, 1000)
== HAL_OK);
configASSERT(std::equal(ct, ct + std::extent_v<decltype(ct)>, ctRef) == true);
__HAL_RCC_AES_CLK_DISABLE();
}
void testCBCByteSwapKeyIVBigEndian()
{
__HAL_RCC_AES_CLK_ENABLE();
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/aesmmt.zip
// CBCMMT128.rsp Encrypt Count 0
// CRYP_BYTE_SWAP
uint32_t key[] = {0x1f8e4973, 0x953f3fb0, 0xbd6b1666, 0x2e9a3c17};
static_assert(sizeof(key) == 16);
uint32_t iv[] = {0x2fe2b333, 0xceda8f98, 0xf4a99b40, 0xd2cd34a8};
static_assert(sizeof(iv) == 16);
uint8_t pt[] = {0x45, 0xcf, 0x12, 0x96, 0x4f, 0xc8, 0x24, 0xab, 0x76, 0x61, 0x6a, 0xe2, 0xf4, 0xbf, 0x08, 0x22};
static_assert(sizeof(pt) == 16);
uint8_t ctRef[] = {0x0f, 0x61, 0xc4, 0xd4, 0x4c, 0x51, 0x47, 0xc0, 0x3c, 0x19, 0x5a, 0xd7, 0xe2, 0xcc, 0x12, 0xb2};
static_assert(sizeof(ctRef) == 16);
decltype(ctRef) ct{};
CRYP_HandleTypeDef handle{.Instance = AES,
.Init = {
.DataType = CRYP_BYTE_SWAP,
.KeySize = CRYP_KEYSIZE_128B,
.pKey = (uint32_t *)key,
.pInitVect = (uint32_t *)iv,
.Algorithm = CRYP_AES_CBC,
.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE,
}};
configASSERT(HAL_CRYP_Init(&handle) == HAL_OK);
configASSERT(HAL_CRYP_Encrypt(&handle, (uint32_t *)pt, std::extent_v<decltype(pt)>, (uint32_t *)ct, 1000)
== HAL_OK);
configASSERT(std::equal(ct, ct + std::extent_v<decltype(ct)>, ctRef) == true);
__HAL_RCC_AES_CLK_DISABLE();
}
void testCBCByteSwap()
{
__HAL_RCC_AES_CLK_ENABLE();
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/aesmmt.zip
// CBCMMT128.rsp Encrypt Count 0
// CRYP_BYTE_SWAP
uint8_t key[] = {0x1f, 0x8e, 0x49, 0x73, 0x95, 0x3f, 0x3f, 0xb0, 0xbd, 0x6b, 0x16, 0x66, 0x2e, 0x9a, 0x3c, 0x17};
static_assert(sizeof(key) == 16);
uint8_t iv[] = {0x2f, 0xe2, 0xb3, 0x33, 0xce, 0xda, 0x8f, 0x98, 0xf4, 0xa9, 0x9b, 0x40, 0xd2, 0xcd, 0x34, 0xa8};
static_assert(sizeof(iv) == 16);
uint8_t pt[] = {0x45, 0xcf, 0x12, 0x96, 0x4f, 0xc8, 0x24, 0xab, 0x76, 0x61, 0x6a, 0xe2, 0xf4, 0xbf, 0x08, 0x22};
static_assert(sizeof(pt) == 16);
uint8_t ctRef[] = {0x0f, 0x61, 0xc4, 0xd4, 0x4c, 0x51, 0x47, 0xc0, 0x3c, 0x19, 0x5a, 0xd7, 0xe2, 0xcc, 0x12, 0xb2};
static_assert(sizeof(ctRef) == 16);
decltype(ctRef) ct{};
CRYP_HandleTypeDef handle{.Instance = AES,
.Init = {
.DataType = CRYP_BYTE_SWAP,
.KeySize = CRYP_KEYSIZE_128B,
.pKey = (uint32_t *)key,
.pInitVect = (uint32_t *)iv,
.Algorithm = CRYP_AES_CBC,
.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE,
}};
configASSERT(HAL_CRYP_Init(&handle) == HAL_OK);
configASSERT(HAL_CRYP_Encrypt(&handle, (uint32_t *)pt, std::extent_v<decltype(pt)>, (uint32_t *)ct, 1000)
== HAL_OK);
configASSERT(std::equal(ct, ct + std::extent_v<decltype(ct)>, ctRef) == true); // FAILS
__HAL_RCC_AES_CLK_DISABLE();
}
Hello,
In fact, the key and IV cannot be transmitted in little-endian format; they must always be sent in a one direction.
Regards,
Correct, This was your design decision. Thus the request to add the option to feed key & IV in little-endian.
Hello @fermentedfly,
I apologize, but there is no support planned for the 'little-endian' format for key and IV.
Please allow me to close the issue, thanks again for your contribution
Regards, Rania
stm32u5xx_hal_cryp
We use AES in byte mode (
CRYP_DATATYPE_8B
).CRYP_ConfigTypeDef provides the option to set the
DataType
. This works fine for the data fed into AES but KEY & IV are passed in in modeCRYP_DATATYPE_32B
regardless of the setup ofDataType
.see
static void CRYP_SetIV(CRYP_HandleTypeDef *hcryp)
&static void CRYP_SetKey(CRYP_HandleTypeDef *hcryp, uint32_t KeySize)
.This is especially problematic since key & iv are not passed to the hardware registers during
HAL_CRYP_Init
orHAL_CRYP_SetConfig
but when callingHAL_CRYP_Encrypt
which means we can't use local (stack) variables to correct the data alignment ourselves.Please update
CRYP_SetIV
&CRYP_SetKey
so they can deal with all modes ofDataType
.Thanks, Manuel