in Drivers/STM32U5xx_HAL/Src/stm32u5xx_hal_cryp.c [3542:3885]
static HAL_StatusTypeDef CRYP_AESGCM_Process_IT(CRYP_HandleTypeDef *hcryp)
{
uint32_t count;
uint32_t loopcounter;
uint32_t lastwordsize;
uint32_t npblb;
uint32_t dokeyivconfig = 1U; /* By default, carry out peripheral Key and IV configuration */
uint32_t headersize_in_bytes;
uint32_t tmp;
uint32_t mask[12] = {0x0U, 0xFF000000U, 0xFFFF0000U, 0xFFFFFF00U, /* 32-bit data type */
0x0U, 0x0000FF00U, 0x0000FFFFU, 0xFF00FFFFU, /* 16-bit data type */
0x0U, 0x000000FFU, 0x0000FFFFU, 0x00FFFFFFU
}; /* 8-bit data type */
#if (USE_HAL_CRYP_SUSPEND_RESUME == 1U)
if ((hcryp->Phase == CRYP_PHASE_HEADER_SUSPENDED) || (hcryp->Phase == CRYP_PHASE_PAYLOAD_SUSPENDED))
{
CRYP_PhaseProcessingResume(hcryp);
return HAL_OK;
}
#endif /* USE_HAL_CRYP_SUSPEND_RESUME */
/* Manage header size given in bytes to handle cases where
header size is not a multiple of 4 bytes */
if (hcryp->Init.HeaderWidthUnit == CRYP_HEADERWIDTHUNIT_WORD)
{
headersize_in_bytes = hcryp->Init.HeaderSize * 4U;
}
else
{
headersize_in_bytes = hcryp->Init.HeaderSize;
}
if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE)
{
if (hcryp->KeyIVConfig == 1U)
{
/* If the Key and IV configuration has to be done only once
and if it has already been done, skip it */
dokeyivconfig = 0U;
hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */
}
else
{
/* If the Key and IV configuration has to be done only once
and if it has not been done already, do it and set KeyIVConfig
to keep track it won't have to be done again next time */
hcryp->KeyIVConfig = 1U;
hcryp->SizesSum = hcryp->Size; /* Merely store payload length */
}
}
else
{
hcryp->SizesSum = hcryp->Size;
}
/* Configure Key, IV and process message (header and payload) */
if (dokeyivconfig == 1U)
{
/* Reset CrypHeaderCount */
hcryp->CrypHeaderCount = 0U;
/******************************* Init phase *********************************/
CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT);
/* Set the Key */
if (hcryp->Init.KeyMode != CRYP_KEYMODE_SHARED)
{
CRYP_SetKey(hcryp, hcryp->Init.KeySize);
}
else /*after sharing the key, AES should set KMOD[1:0] to 00.*/
{
hcryp->Instance->CR &= ~CRYP_KEYMODE_SHARED;
}
/* Set the initialization vector and the counter : Initial Counter Block (ICB)*/
CRYP_SetIV(hcryp);
/* Enable the CRYP peripheral */
__HAL_CRYP_ENABLE(hcryp);
/* just wait for hash computation */
count = CRYP_TIMEOUT_GCMCCMINITPHASE;
do
{
count--;
if (count == 0U)
{
/* Disable the CRYP peripheral clock */
__HAL_CRYP_DISABLE(hcryp);
/* Change state */
hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
hcryp->State = HAL_CRYP_STATE_READY;
__HAL_UNLOCK(hcryp);
return HAL_ERROR;
}
} while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF));
/* Clear CCF flag */
__HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CLEAR_CCF);
/***************************** Header phase *********************************/
/* Select header phase */
CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER);
/* Enable computation complete flag and error interrupts */
__HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_RWEIE | CRYP_IT_KEIE);
/* Enable the CRYP peripheral */
__HAL_CRYP_ENABLE(hcryp);
if (hcryp->Init.HeaderSize == 0U) /*header phase is skipped*/
{
/* Set the phase */
hcryp->Phase = CRYP_PHASE_PROCESS;
/* Select payload phase once the header phase is performed */
MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_PHASE_PAYLOAD);
/* Set to 0 the number of non-valid bytes using NPBLB register*/
MODIFY_REG(hcryp->Instance->CR, AES_CR_NPBLB, 0U);
/* Write the payload Input block in the IN FIFO */
if (hcryp->Size == 0U)
{
/* Disable interrupts */
__HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_RWEIE | CRYP_IT_KEIE);
/* Change the CRYP state */
hcryp->State = HAL_CRYP_STATE_READY;
__HAL_UNLOCK(hcryp);
}
else if (hcryp->Size >= 16U)
{
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
if (hcryp->CrypInCount == (hcryp->Size / 4U))
{
/* Call Input transfer complete callback */
#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U)
/*Call registered Input complete callback*/
hcryp->InCpltCallback(hcryp);
#else
/*Call legacy weak Input complete callback*/
HAL_CRYP_InCpltCallback(hcryp);
#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
}
}
else /* Size < 16Bytes : first block is the last block*/
{
/* Size should be %4 otherwise Tag will be incorrectly generated for GCM Encryption:
Workaround is implemented in polling mode, so if last block of
payload <128bit do not use CRYP_Encrypt_IT otherwise TAG is incorrectly generated for GCM Encryption. */
/* Compute the number of padding bytes in last block of payload */
npblb = 16U - ((uint32_t)hcryp->Size);
if ((hcryp->Instance->CR & AES_CR_MODE) == CRYP_OPERATINGMODE_ENCRYPT)
{
/* Set to 0 the number of non-valid bytes using NPBLB register*/
MODIFY_REG(hcryp->Instance->CR, AES_CR_NPBLB, npblb << 20U);
}
/* Number of valid words (lastwordsize) in last block */
if ((npblb % 4U) == 0U)
{
lastwordsize = (16U - npblb) / 4U;
}
else
{
lastwordsize = ((16U - npblb) / 4U) + 1U;
}
/* last block optionally pad the data with zeros*/
for (loopcounter = 0U; loopcounter < lastwordsize ; loopcounter++)
{
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
}
while (loopcounter < 4U)
{
/* pad the data with zeros to have a complete block */
hcryp->Instance->DINR = 0x0U;
loopcounter++;
}
}
}
/* Enter header data */
/* Cher first whether header length is small enough to enter the full header in one shot */
else if (headersize_in_bytes <= 16U)
{
/* Write header data, padded with zeros if need be */
for (loopcounter = 0U; (loopcounter < (headersize_in_bytes / 4U)); loopcounter++)
{
hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
hcryp->CrypHeaderCount++ ;
}
/* If the header size is a multiple of words */
if ((headersize_in_bytes % 4U) == 0U)
{
/* Pad the data with zeros to have a complete block */
while (loopcounter < 4U)
{
hcryp->Instance->DINR = 0x0U;
loopcounter++;
hcryp->CrypHeaderCount++;
}
}
else
{
/* Enter last bytes, padded with zeros */
tmp = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
tmp &= mask[(hcryp->Init.DataType * 2U) + (headersize_in_bytes % 4U)];
hcryp->Instance->DINR = tmp;
loopcounter++;
hcryp->CrypHeaderCount++ ;
/* Pad the data with zeros to have a complete block */
while (loopcounter < 4U)
{
hcryp->Instance->DINR = 0x0U;
loopcounter++;
hcryp->CrypHeaderCount++;
}
}
/* Call Input transfer complete callback */
#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U)
/*Call registered Input complete callback*/
hcryp->InCpltCallback(hcryp);
#else
/*Call legacy weak Input complete callback*/
HAL_CRYP_InCpltCallback(hcryp);
#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
}
else
{
/* Write the first input header block in the Input FIFO,
the following header data will be fed after interrupt occurrence */
hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
hcryp->CrypHeaderCount++;
hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
hcryp->CrypHeaderCount++;
hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
hcryp->CrypHeaderCount++;
hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount);
hcryp->CrypHeaderCount++;
}
} /* end of if (dokeyivconfig == 1U) */
else /* Key and IV have already been configured,
header has already been processed;
only process here message payload */
{
/* Enable computation complete flag and error interrupts */
__HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_RWEIE | CRYP_IT_KEIE);
/* Set to 0 the number of non-valid bytes using NPBLB register*/
MODIFY_REG(hcryp->Instance->CR, AES_CR_NPBLB, 0U);
/* Write the payload Input block in the IN FIFO */
if (hcryp->Size == 0U)
{
/* Disable interrupts */
__HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_RWEIE | CRYP_IT_KEIE);
/* Change the CRYP state */
hcryp->State = HAL_CRYP_STATE_READY;
__HAL_UNLOCK(hcryp);
}
else if (hcryp->Size >= 16U)
{
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
if (hcryp->CrypInCount == (hcryp->Size / 4U))
{
/* Call Input transfer complete callback */
#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U)
/*Call registered Input complete callback*/
hcryp->InCpltCallback(hcryp);
#else
/*Call legacy weak Input complete callback*/
HAL_CRYP_InCpltCallback(hcryp);
#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */
}
}
else /* Size < 16Bytes : first block is the last block*/
{
/* Size should be %4 otherwise Tag will be incorrectly generated for GCM Encryption:
Workaround is implemented in polling mode, so if last block of
payload <128bit do not use CRYP_Encrypt_IT otherwise TAG is incorrectly generated for GCM Encryption. */
/* Compute the number of padding bytes in last block of payload */
npblb = 16U - ((uint32_t)hcryp->Size);
if ((hcryp->Instance->CR & AES_CR_MODE) == CRYP_OPERATINGMODE_ENCRYPT)
{
/* Set to 0 the number of non-valid bytes using NPBLB register*/
MODIFY_REG(hcryp->Instance->CR, AES_CR_NPBLB, npblb << 20U);
}
/* Number of valid words (lastwordsize) in last block */
if ((npblb % 4U) == 0U)
{
lastwordsize = (16U - npblb) / 4U;
}
else
{
lastwordsize = ((16U - npblb) / 4U) + 1U;
}
/* last block optionally pad the data with zeros*/
for (loopcounter = 0U; loopcounter < lastwordsize ; loopcounter++)
{
hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount);
hcryp->CrypInCount++;
}
while (loopcounter < 4U)
{
/* pad the data with zeros to have a complete block */
hcryp->Instance->DINR = 0x0U;
loopcounter++;
}
}
}
return HAL_OK;
}