/** * @brief generate the GCM authentication TAG. * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains * the configuration information for CRYP module * @param AuthTag: Pointer to the authentication buffer * @param Timeout: Timeout duration * @retval HAL status */ HAL_StatusTypeDef HAL_CRYPEx_AESGCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout) { uint32_t tickstart = 0U; uint64_t headerlength = hcryp->Init.HeaderSize * 32U; /* Header length in bits */ uint64_t inputlength = (hcryp->Size) * 32U; /* input length in bits */ uint32_t tagaddr = (uint32_t)AuthTag; if(hcryp->State == HAL_CRYP_STATE_READY) { /* Process locked */ __HAL_LOCK(hcryp); /* Change the CRYP peripheral state */ hcryp->State = HAL_CRYP_STATE_BUSY; /* Check if initialization phase has already been performed */ if(hcryp->Phase == CRYPEx_PHASE_PROCESS) { /* Change the CRYP phase */ hcryp->Phase = CRYPEx_PHASE_FINAL; } else /* Initialization phase has not been performed*/ { /* Disable the Peripheral */ __HAL_CRYP_DISABLE(hcryp); /* Sequence error code field */ hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE; /* Change the CRYP peripheral state */ hcryp->State = HAL_CRYP_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hcryp); return HAL_ERROR; } /* Disable CRYP to start the final phase */ __HAL_CRYP_DISABLE(hcryp); /* Select final phase */ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH, CRYP_PHASE_FINAL); /*ALGODIR bit must be set to ‘0’.*/ hcryp->Instance->CR &= ~CRYP_CR_ALGODIR; /* Enable the CRYP peripheral */ __HAL_CRYP_ENABLE(hcryp); /* Write the number of bits in header (64 bits) followed by the number of bits in the payload */ if(hcryp->Init.DataType == CRYP_DATATYPE_1B) { hcryp->Instance->DIN = 0U; hcryp->Instance->DIN = __RBIT((uint32_t)(headerlength)); hcryp->Instance->DIN = 0U; hcryp->Instance->DIN = __RBIT((uint32_t)(inputlength)); } else if(hcryp->Init.DataType == CRYP_DATATYPE_8B) { hcryp->Instance->DIN = 0U; hcryp->Instance->DIN = __REV((uint32_t)(headerlength)); hcryp->Instance->DIN = 0U; hcryp->Instance->DIN = __REV((uint32_t)(inputlength)); } else if(hcryp->Init.DataType == CRYP_DATATYPE_16B) { hcryp->Instance->DIN = 0U; hcryp->Instance->DIN = __ROR((uint32_t)headerlength, 16U); hcryp->Instance->DIN = 0U; hcryp->Instance->DIN = __ROR((uint32_t)inputlength, 16U); } else if(hcryp->Init.DataType == CRYP_DATATYPE_32B) { hcryp->Instance->DIN = 0U; hcryp->Instance->DIN = (uint32_t)(headerlength); hcryp->Instance->DIN = 0U; hcryp->Instance->DIN = (uint32_t)(inputlength); } /* Wait for OFNE flag to be raised */ tickstart = HAL_GetTick(); while(HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE)) { /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) { /* Disable the CRYP Peripheral Clock */ __HAL_CRYP_DISABLE(hcryp); /* Change state */ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; hcryp->State = HAL_CRYP_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hcryp); return HAL_ERROR; } } } /* Read the authentication TAG in the output FIFO */ *(uint32_t*)(tagaddr) = hcryp->Instance->DOUT; tagaddr+=4U; *(uint32_t*)(tagaddr) = hcryp->Instance->DOUT; tagaddr+=4U; *(uint32_t*)(tagaddr) = hcryp->Instance->DOUT; tagaddr+=4U; *(uint32_t*)(tagaddr) = hcryp->Instance->DOUT; /* Disable the peripheral */ __HAL_CRYP_DISABLE(hcryp); /* Change the CRYP peripheral state */ hcryp->State = HAL_CRYP_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hcryp); } else { /* Busy error code field */ hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; return HAL_ERROR; } /* Return function status */ return HAL_OK; }
/** * @brief AES CCM Authentication TAG generation. * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains * the configuration information for CRYP module * @param AuthTag: Pointer to the authentication buffer * @param Timeout: Timeout duration * @retval HAL status */ HAL_StatusTypeDef HAL_CRYPEx_AESCCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout) { uint32_t tagaddr = (uint32_t)AuthTag; uint32_t ctr0 [4]={0}; uint32_t ctr0addr = (uint32_t)ctr0; uint32_t tickstart = 0U; if(hcryp->State == HAL_CRYP_STATE_READY) { /* Process locked */ __HAL_LOCK(hcryp); /* Change the CRYP peripheral state */ hcryp->State = HAL_CRYP_STATE_BUSY; /* Check if initialization phase has already been performed */ if(hcryp->Phase == CRYPEx_PHASE_PROCESS) { /* Change the CRYP phase */ hcryp->Phase = CRYPEx_PHASE_FINAL; } else /* Initialization phase has not been performed*/ { /* Disable the peripheral */ __HAL_CRYP_DISABLE(hcryp); /* Sequence error code field */ hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE; /* Change the CRYP peripheral state */ hcryp->State = HAL_CRYP_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hcryp); return HAL_ERROR; } /* Disable CRYP to start the final phase */ __HAL_CRYP_DISABLE(hcryp); /* Select final phase & ALGODIR bit must be set to ‘0’. */ MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH|CRYP_CR_ALGODIR, CRYP_PHASE_FINAL|CRYP_OPERATINGMODE_ENCRYPT); /* Enable the CRYP peripheral */ __HAL_CRYP_ENABLE(hcryp); /* Write the counter block in the IN FIFO, CTR0 information from B0 data has to be swapped according to the DATATYPE*/ ctr0[0]=(hcryp->Init.B0[0]) & CRYP_CCM_CTR0_0; ctr0[1]=hcryp->Init.B0[1]; ctr0[2]=hcryp->Init.B0[2]; ctr0[3]=hcryp->Init.B0[3] & CRYP_CCM_CTR0_3; if(hcryp->Init.DataType == CRYP_DATATYPE_8B) { hcryp->Instance->DIN = __REV(*(uint32_t*)(ctr0addr)); ctr0addr+=4; hcryp->Instance->DIN = __REV(*(uint32_t*)(ctr0addr)); ctr0addr+=4; hcryp->Instance->DIN = __REV(*(uint32_t*)(ctr0addr)); ctr0addr+=4; hcryp->Instance->DIN = __REV(*(uint32_t*)(ctr0addr)); } else if(hcryp->Init.DataType == CRYP_DATATYPE_16B) { hcryp->Instance->DIN = __ROR(*(uint32_t*)(ctr0addr), 16U); ctr0addr+=4; hcryp->Instance->DIN = __ROR(*(uint32_t*)(ctr0addr), 16U); ctr0addr+=4; hcryp->Instance->DIN = __ROR(*(uint32_t*)(ctr0addr), 16U); ctr0addr+=4; hcryp->Instance->DIN = __ROR(*(uint32_t*)(ctr0addr), 16U); } else if(hcryp->Init.DataType == CRYP_DATATYPE_1B) { hcryp->Instance->DIN = __RBIT(*(uint32_t*)(ctr0addr)); ctr0addr+=4; hcryp->Instance->DIN = __RBIT(*(uint32_t*)(ctr0addr)); ctr0addr+=4; hcryp->Instance->DIN = __RBIT(*(uint32_t*)(ctr0addr)); ctr0addr+=4; hcryp->Instance->DIN = __RBIT(*(uint32_t*)(ctr0addr)); } else { hcryp->Instance->DIN = *(uint32_t*)(ctr0addr); ctr0addr+=4; hcryp->Instance->DIN = *(uint32_t*)(ctr0addr); ctr0addr+=4; hcryp->Instance->DIN = *(uint32_t*)(ctr0addr); ctr0addr+=4; hcryp->Instance->DIN = *(uint32_t*)(ctr0addr);; } /* Wait for OFNE flag to be raised */ tickstart = HAL_GetTick(); while(HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE)) { /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) { /* Disable the CRYP peripheral Clock */ __HAL_CRYP_DISABLE(hcryp); /* Change state */ hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; hcryp->State = HAL_CRYP_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hcryp); return HAL_ERROR; } } } /* Read the Auth TAG in the IN FIFO */ *(uint32_t*)(tagaddr) = hcryp->Instance->DOUT; tagaddr+=4U; *(uint32_t*)(tagaddr) = hcryp->Instance->DOUT; tagaddr+=4U; *(uint32_t*)(tagaddr) = hcryp->Instance->DOUT; tagaddr+=4U; *(uint32_t*)(tagaddr) = hcryp->Instance->DOUT; /* Change the CRYP peripheral state */ hcryp->State = HAL_CRYP_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hcryp); /* Disable CRYP */ __HAL_CRYP_DISABLE(hcryp); } else { /* Busy error code field */ hcryp->ErrorCode = HAL_CRYP_ERROR_BUSY; return HAL_ERROR; } /* Return function status */ return HAL_OK; }
/** * @brief Initialize the CRYP according to the specified * parameters in the CRYP_InitTypeDef and initialize the associated handle. * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains * the configuration information for CRYP module * @retval HAL status */ HAL_StatusTypeDef HAL_CRYP_Init(CRYP_HandleTypeDef *hcryp) { /* Check the CRYP handle allocation */ if(hcryp == NULL) { return HAL_ERROR; } /* Check the instance */ assert_param(IS_AES_ALL_INSTANCE(hcryp->Instance)); /* Check the parameters */ assert_param(IS_CRYP_KEYSIZE(hcryp->Init.KeySize)); assert_param(IS_CRYP_DATATYPE(hcryp->Init.DataType)); assert_param(IS_CRYP_ALGOMODE(hcryp->Init.OperatingMode)); /* ChainingMode parameter is irrelevant when mode is set to Key derivation */ if (hcryp->Init.OperatingMode != CRYP_ALGOMODE_KEYDERIVATION) { assert_param(IS_CRYP_CHAINMODE(hcryp->Init.ChainingMode)); } assert_param(IS_CRYP_WRITE(hcryp->Init.KeyWriteFlag)); /*========================================================*/ /* Check the proper operating/chaining modes combinations */ /*========================================================*/ /* Check the proper chaining when the operating mode is key derivation and decryption */ if ((hcryp->Init.OperatingMode == CRYP_ALGOMODE_KEYDERIVATION_DECRYPT) &&\ ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CTR) \ || (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC) \ || (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC))) { return HAL_ERROR; } /* Check that key derivation is not set in CMAC mode */ if ((hcryp->Init.OperatingMode == CRYP_ALGOMODE_KEYDERIVATION) && (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)) { return HAL_ERROR; } /*================*/ /* Initialization */ /*================*/ /* Initialization start */ if(hcryp->State == HAL_CRYP_STATE_RESET) { /* Allocate lock resource and initialize it */ hcryp->Lock = HAL_UNLOCKED; /* Init the low level hardware */ HAL_CRYP_MspInit(hcryp); } /* Change the CRYP state */ hcryp->State = HAL_CRYP_STATE_BUSY; /* Disable the Peripheral */ __HAL_CRYP_DISABLE(); /*=============================================================*/ /* AES initialization common to all operating modes */ /*=============================================================*/ /* Set the Key size selection */ MODIFY_REG(hcryp->Instance->CR, AES_CR_KEYSIZE, hcryp->Init.KeySize); /* Set the default CRYP phase when this parameter is not used. Phase is updated below in case of GCM/GMAC/CMAC setting. */ hcryp->Phase = HAL_CRYP_PHASE_NOT_USED; /*=============================================================*/ /* Carry on the initialization based on the AES operating mode */ /*=============================================================*/ /* Key derivation */ if (hcryp->Init.OperatingMode == CRYP_ALGOMODE_KEYDERIVATION) { MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_ALGOMODE_KEYDERIVATION); /* Configure the Key registers */ if (CRYP_SetKey(hcryp) != HAL_OK) { return HAL_ERROR; } } else /* Encryption / Decryption (with or without key derivation) / authentication */ { /* Set data type, operating and chaining modes. In case of GCM or GMAC, data type is forced to 0b00 */ if (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC) { MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE|AES_CR_MODE|AES_CR_CHMOD, hcryp->Init.OperatingMode|hcryp->Init.ChainingMode); } else { MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE|AES_CR_MODE|AES_CR_CHMOD, hcryp->Init.DataType|hcryp->Init.OperatingMode|hcryp->Init.ChainingMode); } /* Specify the encryption/decryption phase in case of Galois counter mode (GCM), Galois message authentication code (GMAC) or cipher message authentication code (CMAC) */ if ((hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_GCM_GMAC) || (hcryp->Init.ChainingMode == CRYP_CHAINMODE_AES_CMAC)) { MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, hcryp->Init.GCMCMACPhase); hcryp->Phase = HAL_CRYP_PHASE_START; } /* Configure the Key registers if no need to bypass this step */ if (hcryp->Init.KeyWriteFlag == CRYP_KEY_WRITE_ENABLE) { if (CRYP_SetKey(hcryp) != HAL_OK) { return HAL_ERROR; } } /* If applicable, configure the Initialization Vector */ if (hcryp->Init.ChainingMode != CRYP_CHAINMODE_AES_ECB) { if (CRYP_SetInitVector(hcryp) != HAL_OK) { return HAL_ERROR; } } } /* Reset CrypInCount and CrypOutCount */ hcryp->CrypInCount = 0; hcryp->CrypOutCount = 0; /* Reset ErrorCode field */ hcryp->ErrorCode = HAL_CRYP_ERROR_NONE; /* Reset Mode suspension request */ hcryp->SuspendRequest = HAL_CRYP_SUSPEND_NONE; /* Change the CRYP state */ hcryp->State = HAL_CRYP_STATE_READY; /* Enable the Peripheral */ __HAL_CRYP_ENABLE(); /* Return function status */ return HAL_OK; }