Unexpected Behavior of the STM32 CRYP Module
I'm recently working on benchmarking a various implementations and configurations of cryptographic algorithms such AES-GCM on STM32. Two of these tested function are the following :
void test_aes_hardware(void)
{
uint32_t plaintext[DATA_SIZE/4];
uint32_t ciphertext[DATA_SIZE/4];
uint32_t decrypted[DATA_SIZE/4];
uint8_t key_bytes[32];
uint8_t iv_bytes[16];
uint32_t key[8];
uint32_t iv[4];
uint8_t ikm[4];
uint8_t salt[4];
uint8_t info1[] = "HW_AES_KEY";
uint8_t info2[] = "HW_AES_IV";
uint32_t rnd;
/* RNG */
HAL_RNG_GenerateRandomNumber(&hrng, &rnd);
memcpy(ikm, &rnd, 4);
HAL_RNG_GenerateRandomNumber(&hrng, &rnd);
memcpy(salt, &rnd, 4);
/* KDF */
xkdfBlake(key_bytes, 32, ikm, 4, salt, 4, info1, sizeof(info1));
xkdfBlake(iv_bytes, 16, ikm, 4, salt, 4, info2, sizeof(info2));
memcpy(key, key_bytes, 32);
memcpy(iv, iv_bytes, 16);
for (int i = 0; i < DATA_SIZE / 4; i++) {
uint32_t w = (i*4 + 1)
|((i*4 + 2) << 8)
|((i*4 + 3) << 16)
|((i*4 + 4) << 24);
plaintext[i] = w;
}
/* Configure CRYP */
hcryp.Instance = CRYP;
hcryp.Init.DataType = CRYP_DATATYPE_32B;
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
hcryp.Init.pKey = key;
hcryp.Init.Algorithm = CRYP_AES_GCM;
hcryp.Init.pInitVect = iv;
hcryp.Init.Header = NULL;
hcryp.Init.HeaderSize = 0;
HAL_CRYP_Init(&hcryp);
bench_start();
HAL_CRYP_Encrypt(&hcryp,
plaintext,
DATA_SIZE/4,
ciphertext,HAL_MAX_DELAY);
while (HAL_CRYP_GetState(&hcryp) != HAL_CRYP_STATE_READY);
uint32_t time = bench_stop();
HAL_CRYP_Decrypt(&hcryp,
ciphertext,
DATA_SIZE/4,
decrypted,
HAL_MAX_DELAY);
while (HAL_CRYP_GetState(&hcryp) != HAL_CRYP_STATE_READY);
if (memcmp(plaintext, decrypted, DATA_SIZE) != 0) {
printf("Mismatch!\n");
Error_Handler();;
}
printf("AES-GCM Hardware without DMA: %lu us\r\n", time);
}The first one demonstarte the use of AES-GCM through CRYP module.
void test_aes_hardware_dma(void)
{
uint32_t plaintext[DATA_SIZE/4] __attribute__((aligned(32)));
uint32_t ciphertext[DATA_SIZE/4] __attribute__((aligned(32)));
uint32_t decrypted[DATA_SIZE/4] __attribute__((aligned(32)));
uint8_t key_bytes[32];
uint8_t iv_bytes[16];
uint32_t key[8] __attribute__((aligned(32)));
uint32_t iv[4] __attribute__((aligned(32)));
uint8_t ikm[4];
uint8_t salt[4];
uint8_t info1[] = "HW_AES_KEY";
uint8_t info2[] = "HW_AES_IV";
uint32_t rnd;
/* RNG */
HAL_RNG_GenerateRandomNumber(&hrng, &rnd);
memcpy(ikm, &rnd, 4);
HAL_RNG_GenerateRandomNumber(&hrng, &rnd);
memcpy(salt, &rnd, 4);
/* KDF */
xkdfBlake(key_bytes, 32, ikm, 4, salt, 4, info1, sizeof(info1));
xkdfBlake(iv_bytes, 16, ikm, 4, salt, 4, info2, sizeof(info2));
memcpy(key, key_bytes, 32);
memcpy(iv, iv_bytes, 16);
for (int i = 0; i < DATA_SIZE / 4; i++) {
uint32_t w = (i*4 + 1)
| ((i*4 + 2) << 8)
| ((i*4 + 3) << 16)
| ((i*4 + 4) << 24);
plaintext[i] = w;
}
SCB_CleanDCache_by_Addr((uint32_t*)plaintext, DATA_SIZE);
SCB_CleanDCache_by_Addr((uint32_t*)key, sizeof(key));
SCB_CleanDCache_by_Addr((uint32_t*)iv, sizeof(iv));
/* Configure CRYP */
hcryp.Instance = CRYP;
hcryp.Init.DataType = CRYP_DATATYPE_32B;
hcryp.Init.KeySize = CRYP_KEYSIZE_256B;
hcryp.Init.pKey = key;
hcryp.Init.Algorithm = CRYP_AES_GCM;
hcryp.Init.pInitVect = iv;
hcryp.Init.Header = NULL;
hcryp.Init.HeaderSize = 0;
HAL_CRYP_Init(&hcryp);
CrypCompleteDetected = 0;
bench_start();
HAL_CRYP_Encrypt_DMA(&hcryp,
plaintext,
DATA_SIZE/4,
ciphertext);
while (!CrypCompleteDetected);
SCB_InvalidateDCache_by_Addr((uint32_t*)ciphertext, DATA_SIZE);
uint32_t time = bench_stop();
CrypCompleteDetected = 0;
HAL_CRYP_Decrypt_DMA(&hcryp,
ciphertext,
DATA_SIZE/4,
decrypted);
while (!CrypCompleteDetected);
SCB_InvalidateDCache_by_Addr((uint32_t*)decrypted, DATA_SIZE);
if (memcmp(plaintext, decrypted, DATA_SIZE) != 0) {
printf("Mismatch!\n");
Error_Handler();
}
printf("AES-GCM Hardware DMA: %lu us\r\n", time);
}The second one use DMA to transfer data between RAM and CRYP peripheral
When starting the program i got normal results with DATA_SIZE<50Kib. But after that I start getting Mismatches results. When I compare for example only the 100 fisrt bytes it seems that the decrypted data match the initial plaintext and I got an absurd results showing that the encryption exec time of 100Kib < the encryption exec time of 50Kib.
Please feel free to ask me for additional informations.
Thank you.
