Skip to main content
Associate III
February 14, 2025
Solved

STM32U585: AES GCM Tag mismatch

  • February 14, 2025
  • 2 replies
  • 2309 views

Good afternoon,

we are facing issue with AES GCM Tag generated with STM32U585.

In particular we compare the results generated by the microcontroller with the ones generated by an application developed with C#.

This is the code running on the microcontroller

SafeDev_0-1739541887725.png

Key size is 256 Bit set to all 0 just to speed operations. Tag size is 128 bit. I know that the IV vector must have the last byte set as 2 an I dit it as requested.

 

 

 

 

uint32_t pKeyAES[8] = {0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000};

uint32_t pInitVectAES[4] = {0x00000000,0x00000000,0x00000000,0x00000002};

__ALIGN_BEGIN static const uint32_t HeaderAES[4] __ALIGN_END = {

0x24825602,0xbd12a984,0xe0092d3e,0x448eda5f};

 

 

 

Plaintext is a simple 48 bytes buffer (so a multiple of 16).

The EncryptedText is identical to the one generated by the application: good.

On the other hand the generated Tag is always different....maybe we are doing something wrong....could you help us with this topic?

Thanks

Best regards

Best answer by CMYL

Hi @SafeDev 

So sorry again, seems I missed some modifications in the last main.c file. Attached the correct one.

This time I did the full test as you see the snapshot below. We need 0-padding  of both PlainText and CipherText arrays during both encryption and decryption. Otherwise, the last word of the PT and CT streams will be different from the provided NIST vectors. The added "0" will be ignored by passing the correct size in bytes of PT and CT.

 

CMYL_0-1742600082703.png

Below the modified PT/CT streams with padding and Attached the new main.c file.

I will ask internally to either update the CRYP drivers API or give clear guidelines to show how to handle inputs that are not multiple of  32-bits.

uint32_t Plaintext[] = { /*51 bytes */
 0xe7d1dcf6, 
 0x68e28768,
 0x61940e01,
 0x2fe52a98,
 0xdacbd78a,
 0xb63c0884,
 0x2cc9801e,
 0xa581682a,
 0xd54af0c3,
 0x4d0d7f6f,
 0x59e8ee0b,
 0xf4900e0f,
 0xd8504200 /* padding here is mandatory */
};
uint32_t Ciphertext[] = { /* 51 bytes */
 0x8886e196,
 0x010cb384,
 0x9d9c1a18,
 0x2abe1eea,
 0xb0a5f3ca,
 0x423c3669,
 0xa4a8703c,
 0x0f146e8e,
 0x956fb122,
 0xe0d721b8,
 0x69d2b6fc,
 0xd4216d7d,
 0x4d375800 /* padding here is mandatory */

 Best regards

2 replies

Technical Moderator
March 10, 2025

Ciao @SafeDev 

 Sorry for my late answer. I want to ask if Tag is always different whatever the vector test or just when the key and IV are Zeros ? 

Can you compare the computed TAG of your implementation versus the vector test provided by ~\STM32Cube_FW_U5_V1.7.0\Projects\B-U585I-IOT02A\Examples\CRYP\CRYP_AES_GCM ?

 

__ALIGN_BEGIN static const uint32_t pKeyAES[4] __ALIGN_END = {
 0xC939CC13,0x397C1D37,0xDE6AE0E1,0xCB7C423C};
__ALIGN_BEGIN static const uint32_t pInitVectAES[4] __ALIGN_END = {
 0xB3D8CC01,0x7CBB89B3,0x9E0F67E2,0x00000002};
__ALIGN_BEGIN static const uint32_t HeaderAES[4] __ALIGN_END = {
 0x24825602,0xbd12a984,0xe0092d3e,0x448eda5f};

/* USER CODE BEGIN PV */
uint32_t Plaintext[PLAINTEXT_SIZE] = {0xc3b3c41f,0x113a31b7,0x3d9a5cd4,0x32103069};

uint32_t Ciphertext[4] = {0x93FE7D9E,0x9BFD1034,0x8A5606E5,0xCAFA7354};

uint32_t ExpectedTAG[4]={0x0032A1DC,0x85F1C978,0x6925A2E7,0x1D8272DD};

 

 

Best regards

 

SafeDevAuthor
Associate III
March 11, 2025

Hi CMYL,

thanks for the feedback.

I want to ask if Tag is always different whatever the vector test or just when the key and IV are Zeros ?

Yes, the TAG is always different even if I change the IV or the key.

Can you compare the computed TAG of your implementation versus the vector test provide.

Yes for sure.

First of all this is my running code

SafeDev_3-1741674243897.png

In order to be compliant with your example I have to change a little bit my AES configuration (Key is downgrade to 128 bit, No byte swap, DataWidthUnit set to word and HeaderWidthUnit set to word).

SafeDev_2-1741674177010.png

With these parameters I could obtain same cyphertext as yours

SafeDev_0-1741674106914.png

but again different TAG

TAG computed by STM32U585

SafeDev_1-1741674153585.png

TAG computed by Visual Studio code

SafeDev_4-1741674333857.png

TAG expected by your code example

uint32_t ExpectedTAG[4]={0x0032A1DC,0x85F1C978,0x6925A2E7,0x1D8272DD};

So we have three different tags.....

Thank you

Best regards

Technical Moderator
March 11, 2025

Hi @SafeDev 

In the MX_AES_Init(void) function, in the field HeaderSize you put : 

hcryp.Init.HeaderSize = 1;

It should be 

hcryp.Init.HeaderSize = 4;

As the the expected tag is computed whith size 4

 

Can you check again ?

Best regards

Technical Moderator
March 11, 2025

Hi @SafeDev 

>> what is the origin of the visual studio code ? Your own code or some built-in code ?

For the validation of this implementation you can refer to NIST vectors examples for AES GCM. Check the gcmEncrypt/decrypt testvectors in this Github

You can check for example the following vector test from gcmEncryptExtIV256.rsp

/** Extract from NIST Special Publication 800-38D
 * gcmEncryptExtIV256.rsp
[Keylen = 128]
[IVlen = 96]
[PTlen = 408]
[AADlen = 384]
[Taglen = 128]

Count = 0
Key = 463b412911767d57a0b33969e674ffe7845d313b88c6fe312f3d724be68e1fca
IV = 611ce6f9a6880750de7da6cb
PT = e7d1dcf668e2876861940e012fe52a98dacbd78ab63c08842cc9801ea581682ad54af0c34d0d7f6f59e8ee0bf4900e0fd85042
AAD = 0a682fbc6192e1b47a5e0868787ffdafe5a50cead3575849990cdd2ea9b3597749403efb4a56684f0c6bde352d4aeec5
CT = 8886e196010cb3849d9c1a182abe1eeab0a5f3ca423c3669a4a8703c0f146e8e956fb122e0d721b869d2b6fcd4216d7d4d3758
Tag = 2469cecd70fd98fec9264f71df1aee9a
 */
const uint8_t Key[] =
{
 0x46, 0x3b, 0x41, 0x29, 0x11, 0x76, 0x7d, 0x57, 0xa0, 0xb3, 0x39, 0x69, 0xe6, 0x74, 0xff, 0xe7,
 0x84, 0x5d, 0x31, 0x3b, 0x88, 0xc6, 0xfe, 0x31, 0x2f, 0x3d, 0x72, 0x4b, 0xe6, 0x8e, 0x1f, 0xca
};
const uint8_t IV[] =
{
 0x61, 0x1c, 0xe6, 0xf9, 0xa6, 0x88, 0x07, 0x50, 0xde, 0x7d, 0xa6, 0xcb
};
const uint8_t Plaintext[] =
{
 0xe7, 0xd1, 0xdc, 0xf6, 0x68, 0xe2, 0x87, 0x68, 0x61, 0x94, 0x0e, 0x01, 0x2f, 0xe5, 0x2a, 0x98,
 0xda, 0xcb, 0xd7, 0x8a, 0xb6, 0x3c, 0x08, 0x84, 0x2c, 0xc9, 0x80, 0x1e, 0xa5, 0x81, 0x68, 0x2a,
 0xd5, 0x4a, 0xf0, 0xc3, 0x4d, 0x0d, 0x7f, 0x6f, 0x59, 0xe8, 0xee, 0x0b, 0xf4, 0x90, 0x0e, 0x0f,
 0xd8, 0x50, 0x42
};
const uint8_t AddData[] =
{
 0x0a, 0x68, 0x2f, 0xbc, 0x61, 0x92, 0xe1, 0xb4, 0x7a, 0x5e, 0x08, 0x68, 0x78, 0x7f, 0xfd, 0xaf,
 0xe5, 0xa5, 0x0c, 0xea, 0xd3, 0x57, 0x58, 0x49, 0x99, 0x0c, 0xdd, 0x2e, 0xa9, 0xb3, 0x59, 0x77,
 0x49, 0x40, 0x3e, 0xfb, 0x4a, 0x56, 0x68, 0x4f, 0x0c, 0x6b, 0xde, 0x35, 0x2d, 0x4a, 0xee, 0xc5
};
const uint8_t Expected_Ciphertext[] =
{
 0x88, 0x86, 0xe1, 0x96, 0x01, 0x0c, 0xb3, 0x84, 0x9d, 0x9c, 0x1a, 0x18, 0x2a, 0xbe, 0x1e, 0xea,
 0xb0, 0xa5, 0xf3, 0xca, 0x42, 0x3c, 0x36, 0x69, 0xa4, 0xa8, 0x70, 0x3c, 0x0f, 0x14, 0x6e, 0x8e,
 0x95, 0x6f, 0xb1, 0x22, 0xe0, 0xd7, 0x21, 0xb8, 0x69, 0xd2, 0xb6, 0xfc, 0xd4, 0x21, 0x6d, 0x7d,
 0x4d, 0x37, 0x58,
};
const uint8_t Expected_Tag[] =
{
 0x24, 0x69, 0xce, 0xcd, 0x70, 0xfd, 0x98, 0xfe, 0xc9, 0x26, 0x4f, 0x71, 0xdf, 0x1a, 0xee, 0x9a
};

 

SafeDevAuthor
Associate III
March 11, 2025

Hi CMYL,

I just googling for some example. Language is C#.

Do you have some hints about it?

Many Thanks

Best regards

 

Technical Moderator
March 11, 2025

Hi SafeDev,

I just edited my previous comment. Can you check your implementation with NIST test vectors ?

I provided a link and a Test Vector to check if the C# implementation is correct or not

 

Best Regards,