STMicroelectronics / stm32h7xx-hal-driver

Provides the STM32Cube MCU Component "hal_driver" of the STM32H7 series.
BSD 3-Clause "New" or "Revised" License
97 stars 43 forks source link

CRYP api upgrade #36

Closed fermentedfly closed 1 month ago

fermentedfly commented 1 year ago

As far as I can tell the current HAL_CRYP_Encrypt (decrypt as well) provides an all-in-one solution for encryption. This is fine but my use case requires an API that can be initialized and then fed with multiple blocks of data, i.e. something like Init -> Encrypt Block 1 -> Encrypt Block 2 -> ... -> Finalize

Some other HAL implementations, e.g. STM32L4, provide functionality to do this. I've had a look in stm32h7xx_hal_cryp.c and it seems all the required functions are already present but have internal linkage. Please consider making those functions public.

Regards, Manuel

TOUNSTM commented 1 year ago

Hello @fermentedfly,

Thank you for this report. We will get back to you as soon as we analyze it further. This may take some time. Thank you for your comprehension.

With regards,

HBOSTM commented 1 year ago

Hello @fermentedfly,

Thank you for this contribution. Could you please give me more details about this issue, I need to know what internally linked functions you are talking about?

Best Regards,

fermentedfly commented 1 year ago

Hello @HBOSTM ,

I had a deeper look in stm32h7xx_hal_cryp.c and my initial estimate was a bit optimistic. I use AES CBC & GCM. For CBC, making static void CRYP_AES_ProcessData(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) public is enough although a separate Init() would be very convenient.

For GCM, static HAL_StatusTypeDef CRYP_AESGCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) needs refactoring, i.e. the function needs to be split in it's three phases (header, data, finalize) in order to feed data multiple times.

For reference, please have a look in stm32l4xx_hal_cryp.c & stm32l4xx_hal_cryp_ex.c. It got my use case (both CBC & GCM) to work while using

It would be superb if you can provide a similar API for STM32H7.

Regards, Manuel

ALABSTM commented 2 months ago

ST Internal Reference: 191062

ALABSTM commented 2 months ago

Hi @fermentedfly,

Your proposal has been forwarded to our development teams. I will get back to you once I have their feedback.

With regards,

ALABSTM commented 1 month ago

Hi @fermentedfly,

According to our development teams, both STM32L4 and STM32H7 HAL CRYP drivers offer the same features. There is just a difference in the exposed API names.

Indeed, from the STM32H7 HAL CRYP driver perspective, the exposed APIs are:


Now particularly regarding HAL_CRYP_Encrypt() and HAL_CRYP_Decrypt(), you may have noticed that each API handles different algorithms, as you can see from the code snippet below:

https://github.com/STMicroelectronics/stm32h7xx-hal-driver/blob/6f5e35e30ac09ba7bf44139a97b289d3df53cf9c/Src/stm32h7xx_hal_cryp.c#L947-L955

This means that, instead of having multiple APIs exposed as done for the STM32L4 HAL CRYP driver, like shown below, you just have two. This is easier to handle from a user perspective.

HAL_StatusTypeDef     HAL_CRYP_AESECB_Encrypt(CRYP_HandleTypeDef *hcryp, uint8_t *pPlainData, uint16_t Size, uint8_t *pCypherData, uint32_t Timeout);
HAL_StatusTypeDef     HAL_CRYP_AESECB_Decrypt(CRYP_HandleTypeDef *hcryp, uint8_t *pCypherData, uint16_t Size, uint8_t *pPlainData, uint32_t Timeout);
HAL_StatusTypeDef     HAL_CRYP_AESCBC_Encrypt(CRYP_HandleTypeDef *hcryp, uint8_t *pPlainData, uint16_t Size, uint8_t *pCypherData, uint32_t Timeout);
HAL_StatusTypeDef     HAL_CRYP_AESCBC_Decrypt(CRYP_HandleTypeDef *hcryp, uint8_t *pCypherData, uint16_t Size, uint8_t *pPlainData, uint32_t Timeout);
HAL_StatusTypeDef     HAL_CRYP_AESCTR_Encrypt(CRYP_HandleTypeDef *hcryp, uint8_t *pPlainData, uint16_t Size, uint8_t *pCypherData, uint32_t Timeout);
HAL_StatusTypeDef     HAL_CRYP_AESCTR_Decrypt(CRYP_HandleTypeDef *hcryp, uint8_t *pCypherData, uint16_t Size, uint8_t *pPlainData, uint32_t Timeout);

Note that, to select an algorithm, you simply have to use a simple assignment in your application, as the one shown below (extract from the code snippet provided at the end of this message):

hcryp.Init.Algorithm       = CRYP_AES_GCM;

Last, but not least, the use case you mentioned is already possible using the STM32H7 HAL CRYP driver, as indicated in the ##### How to use this driver ##### section (extract below):

https://github.com/STMicroelectronics/stm32h7xx-hal-driver/blob/6f5e35e30ac09ba7bf44139a97b289d3df53cf9c/Src/stm32h7xx_hal_cryp.c#L81-L85

The code snippet below illustrates how to do this in your application.

CRYP_HandleTypeDef hcryp;

uint32_t timeout            = 10;

uint32_t aes128key[4]       = {0xfeffe992,0x8665731c,0x6d6a8f94,0x67308308};
uint32_t initVector[4]      = {0xcafebabe,0xfacedbad,0xdecaf888,0x00000002};
uint32_t headerMessage[5]   = {0xfeedface,0xdeadbeef,0xfeedface,0xdeadbeef,0xabaddad2};

uint32_t plainText[15]      = {0xd9313225,0xf88406e5,0xa55909c5,0xaff5269a,
                               0x86a7a953,0x1534f7da,0x2e4c303d,0x8a318a72,
                               0x1c3c0c95,0x95680953,0x2fcf0e24,0x49a6b525,
                               0xb16aedf5,0xaa0de657,0xba637b39};
uint32_t encryptedText[16]  = {0};
uint32_t computedAuthTag[4] = {0};

/* Set the CRYP parameters */
hcryp.Instance             = CRYP;
hcryp.Init.Header          = headerMessage;
hcryp.Init.HeaderSize      = 5;
hcryp.Init.DataType        = CRYP_DATATYPE_32B;
hcryp.Init.DataWidthUnit   = CRYP_DATAWIDTHUNIT_WORD;
hcryp.Init.pKey            = aes128key;
hcryp.Init.pInitVect       = initVector;
hcryp.Init.KeySize         = CRYP_KEYSIZE_128B;
hcryp.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ONCE;
hcryp.Init.Algorithm       = CRYP_AES_GCM;

/* Initialize and configure the CRYP peripheral */
if (HAL_CRYP_Init(&hcryp) != HAL_OK)
{
  Error_Handler();
}

/*  Encrypt the plain text through multiple runs */
if (HAL_CRYP_Encrypt(&hcryp, plainText,    8, encryptedText,    timeout) != HAL_OK)
{
  Error_Handler();
}
if (HAL_CRYP_Encrypt(&hcryp, plainText+8,  4, encryptedText+8,  timeout) != HAL_OK)
{
  Error_Handler();
}
if (HAL_CRYP_Encrypt(&hcryp, plainText+12, 3, encryptedText+12, timeout) != HAL_OK)
{
  Error_Handler();
}

/* Compute the authentication TAG */
if (HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, computedAuthTag, timeout) != HAL_OK)
{
  Error_Handler();
}

I hope this makes things clearer and addresses your needs. Please allow me to close this thread. Thank you for your comprehension and thank you again for having tackled the subject.

With regards,