![]() |
|
|||
File indexing completed on 2025-05-11 08:23:07
0001 /** 0002 ****************************************************************************** 0003 * @file stm32h7xx_hal_hash.c 0004 * @author MCD Application Team 0005 * @brief HASH HAL module driver. 0006 * This file provides firmware functions to manage the following 0007 * functionalities of the HASH peripheral: 0008 * + Initialization and de-initialization methods 0009 * + HASH or HMAC processing in polling mode 0010 * + HASH or HMAC processing in interrupt mode 0011 * + HASH or HMAC processing in DMA mode 0012 * + Peripheral State methods 0013 * + HASH or HMAC processing suspension/resumption 0014 * 0015 ****************************************************************************** 0016 * @attention 0017 * 0018 * Copyright (c) 2017 STMicroelectronics. 0019 * All rights reserved. 0020 * 0021 * This software is licensed under terms that can be found in the LICENSE file 0022 * in the root directory of this software component. 0023 * If no LICENSE file comes with this software, it is provided AS-IS. 0024 * 0025 ****************************************************************************** 0026 @verbatim 0027 =============================================================================== 0028 ##### How to use this driver ##### 0029 =============================================================================== 0030 [..] 0031 The HASH HAL driver can be used as follows: 0032 0033 (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit(): 0034 (##) Enable the HASH interface clock using __HASH_CLK_ENABLE() 0035 (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT()) 0036 (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority() 0037 (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ() 0038 (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API 0039 (##) When resorting to DMA-based APIs (e.g. HAL_HASH_xxx_Start_DMA()) 0040 (+++) Enable the DMAx interface clock using 0041 __DMAx_CLK_ENABLE() 0042 (+++) Configure and enable one DMA stream to manage data transfer from 0043 memory to peripheral (input stream). Managing data transfer from 0044 peripheral to memory can be performed only using CPU. 0045 (+++) Associate the initialized DMA handle to the HASH DMA handle 0046 using __HAL_LINKDMA() 0047 (+++) Configure the priority and enable the NVIC for the transfer complete 0048 interrupt on the DMA stream: use 0049 HAL_NVIC_SetPriority() and 0050 HAL_NVIC_EnableIRQ() 0051 0052 (#)Initialize the HASH HAL using HAL_HASH_Init(). This function: 0053 (##) resorts to HAL_HASH_MspInit() for low-level initialization, 0054 (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit. 0055 0056 (#)Three processing schemes are available: 0057 (##) Polling mode: processing APIs are blocking functions 0058 i.e. they process the data and wait till the digest computation is finished, 0059 e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC 0060 (##) Interrupt mode: processing APIs are not blocking functions 0061 i.e. they process the data under interrupt, 0062 e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC 0063 (##) DMA mode: processing APIs are not blocking functions and the CPU is 0064 not used for data transfer i.e. the data transfer is ensured by DMA, 0065 e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA() 0066 for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish() 0067 is then required to retrieve the digest. 0068 0069 (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is 0070 initialized and processes the buffer fed in input. When the input data have all been 0071 fed to the Peripheral, the digest computation can start. 0072 0073 (#)Multi-buffer processing is possible in polling, interrupt and DMA modes. 0074 (##) In polling mode, only multi-buffer HASH processing is possible. 0075 API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one. 0076 User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as 0077 well the computed digest. 0078 0079 (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer, 0080 except for the last one. 0081 User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as 0082 well the computed digest. 0083 0084 (##) In DMA mode, multi-buffer HASH and HMAC processing are possible. 0085 (+++) HASH processing: once initialization is done, MDMAT bit must be set 0086 through __HAL_HASH_SET_MDMAT() macro. 0087 From that point, each buffer can be fed to the Peripheral through HAL_HASH_xxx_Start_DMA() API. 0088 Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT() 0089 macro then wrap-up the HASH processing in feeding the last input buffer through the 0090 same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to 0091 API HAL_HASH_xxx_Finish(). 0092 (+++) HMAC processing (requires to resort to extended functions): 0093 after initialization, the key and the first input buffer are entered 0094 in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and 0095 starts step 2. 0096 The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this 0097 point, the HMAC processing is still carrying out step 2. 0098 Then, step 2 for the last input buffer and step 3 are carried out by a single call 0099 to HAL_HMACEx_xxx_Step2_3_DMA(). 0100 0101 The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish(). 0102 0103 0104 (#)Context swapping. 0105 (##) Two APIs are available to suspend HASH or HMAC processing: 0106 (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode), 0107 (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA. 0108 0109 (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows 0110 to save in memory the Peripheral context. This context can be restored afterwards 0111 to resume the HASH processing thanks to HAL_HASH_ContextRestoring(). 0112 0113 (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension 0114 time, processing can be restarted with the same API call (same API, same handle, 0115 same parameters) as done before the suspension. Relevant parameters to restart at 0116 the proper location are internally saved in the HASH handle. 0117 0118 (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral. 0119 0120 *** Remarks on message length *** 0121 =================================== 0122 [..] 0123 (#) HAL in interruption mode (interruptions driven) 0124 0125 (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes. 0126 This is why, for driver implementation simplicity s sake, user is requested to enter a message the 0127 length of which is a multiple of 4 bytes. 0128 0129 (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR 0130 to specify which bits to discard at the end of the complete message to process only the message bits 0131 and not extra bits. 0132 0133 (##) If user needs to perform a hash computation of a large input buffer that is spread around various places 0134 in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it becomes 0135 necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral. 0136 It is advised to the user to 0137 (+++) achieve the first formatting operation by software then enter the data 0138 (+++) while the Peripheral is processing the first input set, carry out the second formatting 0139 operation by software, to be ready when DINIS occurs. 0140 (+++) repeat step 2 until the whole message is processed. 0141 0142 [..] 0143 (#) HAL in DMA mode 0144 0145 (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis. 0146 The same field described above in HASH_STR is used to specify which bits to discard at the end of the 0147 DMA transfer to process only the message bits and not extra bits. Due to hardware implementation, 0148 this is possible only at the end of the complete message. When several DMA transfers are needed to 0149 enter the message, this is not applicable at the end of the intermediary transfers. 0150 0151 (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive 0152 chunks of data by software while the DMA transfer and processing is on-going for the first parts of 0153 the message. Due to the 32-bit alignment required for the DMA transfer, it is underlined that the 0154 software formatting operation is more complex than in the IT mode. 0155 0156 *** Callback registration *** 0157 =================================== 0158 [..] 0159 (#) The compilation define USE_HAL_HASH_REGISTER_CALLBACKS when set to 1 0160 allows the user to configure dynamically the driver callbacks. 0161 Use function HAL_HASH_RegisterCallback() to register a user callback. 0162 0163 (#) Function HAL_HASH_RegisterCallback() allows to register following callbacks: 0164 (+) InCpltCallback : callback for input completion. 0165 (+) DgstCpltCallback : callback for digest computation completion. 0166 (+) ErrorCallback : callback for error. 0167 (+) MspInitCallback : HASH MspInit. 0168 (+) MspDeInitCallback : HASH MspDeInit. 0169 This function takes as parameters the HAL peripheral handle, the Callback ID 0170 and a pointer to the user callback function. 0171 0172 (#) Use function HAL_HASH_UnRegisterCallback() to reset a callback to the default 0173 weak (surcharged) function. 0174 HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle, 0175 and the Callback ID. 0176 This function allows to reset following callbacks: 0177 (+) InCpltCallback : callback for input completion. 0178 (+) DgstCpltCallback : callback for digest computation completion. 0179 (+) ErrorCallback : callback for error. 0180 (+) MspInitCallback : HASH MspInit. 0181 (+) MspDeInitCallback : HASH MspDeInit. 0182 0183 (#) By default, after the HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET 0184 all callbacks are reset to the corresponding legacy weak (surcharged) functions: 0185 examples HAL_HASH_InCpltCallback(), HAL_HASH_DgstCpltCallback() 0186 Exception done for MspInit and MspDeInit callbacks that are respectively 0187 reset to the legacy weak (surcharged) functions in the HAL_HASH_Init 0188 and HAL_HASH_DeInit only when these callbacks are null (not registered beforehand) 0189 If not, MspInit or MspDeInit are not null, the HAL_HASH_Init and HAL_HASH_DeInit 0190 keep and use the user MspInit/MspDeInit callbacks (registered beforehand). 0191 0192 Callbacks can be registered/unregistered in READY state only. 0193 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered 0194 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used 0195 during the Init/DeInit. 0196 In that case first register the MspInit/MspDeInit user callbacks 0197 using HAL_HASH_RegisterCallback before calling HAL_HASH_DeInit 0198 or HAL_HASH_Init function. 0199 0200 When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or 0201 not defined, the callback registering feature is not available 0202 and weak (surcharged) callbacks are used. 0203 0204 @endverbatim 0205 ****************************************************************************** 0206 */ 0207 0208 /* Includes ------------------------------------------------------------------*/ 0209 #include "stm32h7xx_hal.h" 0210 0211 0212 /** @addtogroup STM32H7xx_HAL_Driver 0213 * @{ 0214 */ 0215 #if defined (HASH) 0216 0217 /** @defgroup HASH HASH 0218 * @ingroup RTEMSBSPsARMSTM32H7 0219 * @brief HASH HAL module driver. 0220 * @{ 0221 */ 0222 0223 #ifdef HAL_HASH_MODULE_ENABLED 0224 0225 /* Private typedef -----------------------------------------------------------*/ 0226 /* Private define ------------------------------------------------------------*/ 0227 /** @defgroup HASH_Private_Constants HASH Private Constants 0228 * @ingroup RTEMSBSPsARMSTM32H7 0229 * @{ 0230 */ 0231 0232 /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status 0233 * @ingroup RTEMSBSPsARMSTM32H7 0234 * @{ 0235 */ 0236 #define HASH_DIGEST_CALCULATION_NOT_STARTED ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */ 0237 #define HASH_DIGEST_CALCULATION_STARTED ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register */ 0238 /** 0239 * @} 0240 */ 0241 0242 /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers 0243 * @ingroup RTEMSBSPsARMSTM32H7 0244 * @{ 0245 */ 0246 #define HASH_NUMBER_OF_CSR_REGISTERS 54U /*!< Number of Context Swap Registers */ 0247 /** 0248 * @} 0249 */ 0250 0251 /** @defgroup HASH_TimeOut_Value HASH TimeOut Value 0252 * @ingroup RTEMSBSPsARMSTM32H7 0253 * @{ 0254 */ 0255 #define HASH_TIMEOUTVALUE 1000U /*!< Time-out value */ 0256 /** 0257 * @} 0258 */ 0259 0260 /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit 0261 * @ingroup RTEMSBSPsARMSTM32H7 0262 * @{ 0263 */ 0264 #define HASH_DMA_SUSPENSION_WORDS_LIMIT 20U /*!< Number of words below which DMA suspension is aborted */ 0265 /** 0266 * @} 0267 */ 0268 0269 /** 0270 * @} 0271 */ 0272 0273 /* Private macro -------------------------------------------------------------*/ 0274 /* Private variables ---------------------------------------------------------*/ 0275 /* Private function prototypes -----------------------------------------------*/ 0276 /** @defgroup HASH_Private_Functions HASH Private Functions 0277 * @ingroup RTEMSBSPsARMSTM32H7 0278 * @{ 0279 */ 0280 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma); 0281 static void HASH_DMAError(DMA_HandleTypeDef *hdma); 0282 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size); 0283 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, 0284 uint32_t Timeout); 0285 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); 0286 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash); 0287 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash); 0288 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout); 0289 /** 0290 * @} 0291 */ 0292 0293 /** @defgroup HASH_Exported_Functions HASH Exported Functions 0294 * @ingroup RTEMSBSPsARMSTM32H7 0295 * @{ 0296 */ 0297 0298 /** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions 0299 * @ingroup RTEMSBSPsARMSTM32H7 0300 * @brief Initialization, configuration and call-back functions. 0301 * 0302 @verbatim 0303 =============================================================================== 0304 ##### Initialization and de-initialization functions ##### 0305 =============================================================================== 0306 [..] This section provides functions allowing to: 0307 (+) Initialize the HASH according to the specified parameters 0308 in the HASH_InitTypeDef and create the associated handle 0309 (+) DeInitialize the HASH peripheral 0310 (+) Initialize the HASH MCU Specific Package (MSP) 0311 (+) DeInitialize the HASH MSP 0312 0313 [..] This section provides as well call back functions definitions for user 0314 code to manage: 0315 (+) Input data transfer to Peripheral completion 0316 (+) Calculated digest retrieval completion 0317 (+) Error management 0318 0319 0320 0321 @endverbatim 0322 * @{ 0323 */ 0324 0325 /** 0326 * @brief Initialize the HASH according to the specified parameters in the 0327 HASH_HandleTypeDef and create the associated handle. 0328 * @note Only MDMAT and DATATYPE bits of HASH Peripheral are set by HAL_HASH_Init(), 0329 * other configuration bits are set by HASH or HMAC processing APIs. 0330 * @note MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for 0331 * multi-buffer HASH processing, user needs to resort to 0332 * __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the 0333 * relevant APIs manage themselves the MDMAT bit. 0334 * @param hhash HASH handle 0335 * @retval HAL status 0336 */ 0337 HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash) 0338 { 0339 /* Check the hash handle allocation */ 0340 if (hhash == NULL) 0341 { 0342 return HAL_ERROR; 0343 } 0344 0345 /* Check the parameters */ 0346 assert_param(IS_HASH_DATATYPE(hhash->Init.DataType)); 0347 0348 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 0349 if (hhash->State == HAL_HASH_STATE_RESET) 0350 { 0351 /* Allocate lock resource and initialize it */ 0352 hhash->Lock = HAL_UNLOCKED; 0353 0354 /* Reset Callback pointers in HAL_HASH_STATE_RESET only */ 0355 hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */ 0356 hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation 0357 completion callback */ 0358 hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */ 0359 if (hhash->MspInitCallback == NULL) 0360 { 0361 hhash->MspInitCallback = HAL_HASH_MspInit; 0362 } 0363 0364 /* Init the low level hardware */ 0365 hhash->MspInitCallback(hhash); 0366 } 0367 #else 0368 if (hhash->State == HAL_HASH_STATE_RESET) 0369 { 0370 /* Allocate lock resource and initialize it */ 0371 hhash->Lock = HAL_UNLOCKED; 0372 0373 /* Init the low level hardware */ 0374 HAL_HASH_MspInit(hhash); 0375 } 0376 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ 0377 0378 /* Change the HASH state */ 0379 hhash->State = HAL_HASH_STATE_BUSY; 0380 0381 /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */ 0382 hhash->HashInCount = 0; 0383 hhash->HashBuffSize = 0; 0384 hhash->HashITCounter = 0; 0385 hhash->NbWordsAlreadyPushed = 0; 0386 /* Reset digest calculation bridle (MDMAT bit control) */ 0387 hhash->DigestCalculationDisable = RESET; 0388 /* Set phase to READY */ 0389 hhash->Phase = HAL_HASH_PHASE_READY; 0390 /* Reset suspension request flag */ 0391 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; 0392 0393 /* Set the data type bit */ 0394 MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType); 0395 /* Reset MDMAT bit */ 0396 __HAL_HASH_RESET_MDMAT(); 0397 /* Reset HASH handle status */ 0398 hhash->Status = HAL_OK; 0399 0400 /* Set the HASH state to Ready */ 0401 hhash->State = HAL_HASH_STATE_READY; 0402 0403 /* Initialise the error code */ 0404 hhash->ErrorCode = HAL_HASH_ERROR_NONE; 0405 0406 /* Return function status */ 0407 return HAL_OK; 0408 } 0409 0410 /** 0411 * @brief DeInitialize the HASH peripheral. 0412 * @param hhash HASH handle. 0413 * @retval HAL status 0414 */ 0415 HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash) 0416 { 0417 /* Check the HASH handle allocation */ 0418 if (hhash == NULL) 0419 { 0420 return HAL_ERROR; 0421 } 0422 0423 /* Change the HASH state */ 0424 hhash->State = HAL_HASH_STATE_BUSY; 0425 0426 /* Set the default HASH phase */ 0427 hhash->Phase = HAL_HASH_PHASE_READY; 0428 0429 /* Reset HashInCount, HashITCounter and HashBuffSize */ 0430 hhash->HashInCount = 0; 0431 hhash->HashBuffSize = 0; 0432 hhash->HashITCounter = 0; 0433 /* Reset digest calculation bridle (MDMAT bit control) */ 0434 hhash->DigestCalculationDisable = RESET; 0435 0436 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 0437 if (hhash->MspDeInitCallback == NULL) 0438 { 0439 hhash->MspDeInitCallback = HAL_HASH_MspDeInit; 0440 } 0441 0442 /* DeInit the low level hardware */ 0443 hhash->MspDeInitCallback(hhash); 0444 #else 0445 /* DeInit the low level hardware: CLOCK, NVIC */ 0446 HAL_HASH_MspDeInit(hhash); 0447 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ 0448 0449 0450 /* Reset HASH handle status */ 0451 hhash->Status = HAL_OK; 0452 0453 /* Set the HASH state to Ready */ 0454 hhash->State = HAL_HASH_STATE_RESET; 0455 0456 /* Initialise the error code */ 0457 hhash->ErrorCode = HAL_HASH_ERROR_NONE; 0458 0459 /* Reset multi buffers accumulation flag */ 0460 hhash->Accumulation = 0U; 0461 0462 /* Return function status */ 0463 return HAL_OK; 0464 } 0465 0466 /** 0467 * @brief Initialize the HASH MSP. 0468 * @param hhash HASH handle. 0469 * @retval None 0470 */ 0471 __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash) 0472 { 0473 /* Prevent unused argument(s) compilation warning */ 0474 UNUSED(hhash); 0475 0476 /* NOTE : This function should not be modified; when the callback is needed, 0477 HAL_HASH_MspInit() can be implemented in the user file. 0478 */ 0479 } 0480 0481 /** 0482 * @brief DeInitialize the HASH MSP. 0483 * @param hhash HASH handle. 0484 * @retval None 0485 */ 0486 __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash) 0487 { 0488 /* Prevent unused argument(s) compilation warning */ 0489 UNUSED(hhash); 0490 0491 /* NOTE : This function should not be modified; when the callback is needed, 0492 HAL_HASH_MspDeInit() can be implemented in the user file. 0493 */ 0494 } 0495 0496 /** 0497 * @brief Input data transfer complete call back. 0498 * @note HAL_HASH_InCpltCallback() is called when the complete input message 0499 * has been fed to the Peripheral. This API is invoked only when input data are 0500 * entered under interruption or through DMA. 0501 * @note In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set), 0502 * HAL_HASH_InCpltCallback() is called at the end of each buffer feeding 0503 * to the Peripheral. 0504 * @param hhash HASH handle. 0505 * @retval None 0506 */ 0507 __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash) 0508 { 0509 /* Prevent unused argument(s) compilation warning */ 0510 UNUSED(hhash); 0511 0512 /* NOTE : This function should not be modified; when the callback is needed, 0513 HAL_HASH_InCpltCallback() can be implemented in the user file. 0514 */ 0515 } 0516 0517 /** 0518 * @brief Digest computation complete call back. 0519 * @note HAL_HASH_DgstCpltCallback() is used under interruption, is not 0520 * relevant with DMA. 0521 * @param hhash HASH handle. 0522 * @retval None 0523 */ 0524 __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash) 0525 { 0526 /* Prevent unused argument(s) compilation warning */ 0527 UNUSED(hhash); 0528 0529 /* NOTE : This function should not be modified; when the callback is needed, 0530 HAL_HASH_DgstCpltCallback() can be implemented in the user file. 0531 */ 0532 } 0533 0534 /** 0535 * @brief Error callback. 0536 * @note Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...) 0537 * to retrieve the error type. 0538 * @param hhash HASH handle. 0539 * @retval None 0540 */ 0541 __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash) 0542 { 0543 /* Prevent unused argument(s) compilation warning */ 0544 UNUSED(hhash); 0545 0546 /* NOTE : This function should not be modified; when the callback is needed, 0547 HAL_HASH_ErrorCallback() can be implemented in the user file. 0548 */ 0549 } 0550 0551 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 0552 /** 0553 * @brief Register a User HASH Callback 0554 * To be used instead of the weak (surcharged) predefined callback 0555 * @param hhash HASH handle 0556 * @param CallbackID ID of the callback to be registered 0557 * This parameter can be one of the following values: 0558 * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID 0559 * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID 0560 * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID 0561 * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID 0562 * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID 0563 * @param pCallback pointer to the Callback function 0564 * @retval status 0565 */ 0566 HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID, 0567 pHASH_CallbackTypeDef pCallback) 0568 { 0569 HAL_StatusTypeDef status = HAL_OK; 0570 0571 if (pCallback == NULL) 0572 { 0573 /* Update the error code */ 0574 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 0575 return HAL_ERROR; 0576 } 0577 /* Process locked */ 0578 __HAL_LOCK(hhash); 0579 0580 if (HAL_HASH_STATE_READY == hhash->State) 0581 { 0582 switch (CallbackID) 0583 { 0584 case HAL_HASH_INPUTCPLT_CB_ID : 0585 hhash->InCpltCallback = pCallback; 0586 break; 0587 0588 case HAL_HASH_DGSTCPLT_CB_ID : 0589 hhash->DgstCpltCallback = pCallback; 0590 break; 0591 0592 case HAL_HASH_ERROR_CB_ID : 0593 hhash->ErrorCallback = pCallback; 0594 break; 0595 0596 case HAL_HASH_MSPINIT_CB_ID : 0597 hhash->MspInitCallback = pCallback; 0598 break; 0599 0600 case HAL_HASH_MSPDEINIT_CB_ID : 0601 hhash->MspDeInitCallback = pCallback; 0602 break; 0603 0604 default : 0605 /* Update the error code */ 0606 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 0607 /* update return status */ 0608 status = HAL_ERROR; 0609 break; 0610 } 0611 } 0612 else if (HAL_HASH_STATE_RESET == hhash->State) 0613 { 0614 switch (CallbackID) 0615 { 0616 case HAL_HASH_MSPINIT_CB_ID : 0617 hhash->MspInitCallback = pCallback; 0618 break; 0619 0620 case HAL_HASH_MSPDEINIT_CB_ID : 0621 hhash->MspDeInitCallback = pCallback; 0622 break; 0623 0624 default : 0625 /* Update the error code */ 0626 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 0627 /* update return status */ 0628 status = HAL_ERROR; 0629 break; 0630 } 0631 } 0632 else 0633 { 0634 /* Update the error code */ 0635 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 0636 /* update return status */ 0637 status = HAL_ERROR; 0638 } 0639 0640 /* Release Lock */ 0641 __HAL_UNLOCK(hhash); 0642 return status; 0643 } 0644 0645 /** 0646 * @brief Unregister a HASH Callback 0647 * HASH Callback is redirected to the weak (surcharged) predefined callback 0648 * @param hhash HASH handle 0649 * @param CallbackID ID of the callback to be unregistered 0650 * This parameter can be one of the following values: 0651 * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID 0652 * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID 0653 * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID 0654 * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID 0655 * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID 0656 * @retval status 0657 */ 0658 HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID) 0659 { 0660 HAL_StatusTypeDef status = HAL_OK; 0661 0662 /* Process locked */ 0663 __HAL_LOCK(hhash); 0664 0665 if (HAL_HASH_STATE_READY == hhash->State) 0666 { 0667 switch (CallbackID) 0668 { 0669 case HAL_HASH_INPUTCPLT_CB_ID : 0670 hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */ 0671 break; 0672 0673 case HAL_HASH_DGSTCPLT_CB_ID : 0674 hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation 0675 completion callback */ 0676 break; 0677 0678 case HAL_HASH_ERROR_CB_ID : 0679 hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */ 0680 break; 0681 0682 case HAL_HASH_MSPINIT_CB_ID : 0683 hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */ 0684 break; 0685 0686 case HAL_HASH_MSPDEINIT_CB_ID : 0687 hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ 0688 break; 0689 0690 default : 0691 /* Update the error code */ 0692 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 0693 /* update return status */ 0694 status = HAL_ERROR; 0695 break; 0696 } 0697 } 0698 else if (HAL_HASH_STATE_RESET == hhash->State) 0699 { 0700 switch (CallbackID) 0701 { 0702 case HAL_HASH_MSPINIT_CB_ID : 0703 hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */ 0704 break; 0705 0706 case HAL_HASH_MSPDEINIT_CB_ID : 0707 hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ 0708 break; 0709 0710 default : 0711 /* Update the error code */ 0712 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 0713 /* update return status */ 0714 status = HAL_ERROR; 0715 break; 0716 } 0717 } 0718 else 0719 { 0720 /* Update the error code */ 0721 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 0722 /* update return status */ 0723 status = HAL_ERROR; 0724 } 0725 0726 /* Release Lock */ 0727 __HAL_UNLOCK(hhash); 0728 return status; 0729 } 0730 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 0731 0732 /** 0733 * @} 0734 */ 0735 0736 /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode 0737 * @ingroup RTEMSBSPsARMSTM32H7 0738 * @brief HASH processing functions using polling mode. 0739 * 0740 @verbatim 0741 =============================================================================== 0742 ##### Polling mode HASH processing functions ##### 0743 =============================================================================== 0744 [..] This section provides functions allowing to calculate in polling mode 0745 the hash value using one of the following algorithms: 0746 (+) MD5 0747 (++) HAL_HASH_MD5_Start() 0748 (++) HAL_HASH_MD5_Accmlt() 0749 (++) HAL_HASH_MD5_Accmlt_End() 0750 (+) SHA1 0751 (++) HAL_HASH_SHA1_Start() 0752 (++) HAL_HASH_SHA1_Accmlt() 0753 (++) HAL_HASH_SHA1_Accmlt_End() 0754 0755 [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start(). 0756 0757 [..] In case of multi-buffer HASH processing (a single digest is computed while 0758 several buffers are fed to the Peripheral), the user can resort to successive calls 0759 to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call 0760 to HAL_HASH_xxx_Accumulate_End(). 0761 0762 @endverbatim 0763 * @{ 0764 */ 0765 0766 /** 0767 * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then 0768 * read the computed digest. 0769 * @note Digest is available in pOutBuffer. 0770 * @param hhash HASH handle. 0771 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0772 * @param Size length of the input buffer in bytes. 0773 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 0774 * @param Timeout Timeout value 0775 * @retval HAL status 0776 */ 0777 HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 0778 uint32_t Timeout) 0779 { 0780 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); 0781 } 0782 0783 /** 0784 * @brief If not already done, initialize the HASH peripheral in MD5 mode then 0785 * processes pInBuffer. 0786 * @note Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed 0787 * several input buffers back-to-back to the Peripheral that will yield a single 0788 * HASH signature once all buffers have been entered. Wrap-up of input 0789 * buffers feeding and retrieval of digest is done by a call to 0790 * HAL_HASH_MD5_Accmlt_End(). 0791 * @note Field hhash->Phase of HASH handle is tested to check whether or not 0792 * the Peripheral has already been initialized. 0793 * @note Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End() 0794 * to read it, feeding at the same time the last input buffer to the Peripheral. 0795 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 0796 * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able 0797 * to manage the ending buffer with a length in bytes not a multiple of 4. 0798 * @param hhash HASH handle. 0799 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0800 * @param Size length of the input buffer in bytes, must be a multiple of 4. 0801 * @retval HAL status 0802 */ 0803 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 0804 { 0805 return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); 0806 } 0807 0808 /** 0809 * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API. 0810 * @note Digest is available in pOutBuffer. 0811 * @param hhash HASH handle. 0812 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0813 * @param Size length of the input buffer in bytes. 0814 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 0815 * @param Timeout Timeout value 0816 * @retval HAL status 0817 */ 0818 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 0819 uint8_t *pOutBuffer, uint32_t Timeout) 0820 { 0821 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); 0822 } 0823 0824 /** 0825 * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then 0826 * read the computed digest. 0827 * @note Digest is available in pOutBuffer. 0828 * @param hhash HASH handle. 0829 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0830 * @param Size length of the input buffer in bytes. 0831 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 0832 * @param Timeout Timeout value 0833 * @retval HAL status 0834 */ 0835 HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 0836 uint32_t Timeout) 0837 { 0838 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); 0839 } 0840 0841 /** 0842 * @brief If not already done, initialize the HASH peripheral in SHA1 mode then 0843 * processes pInBuffer. 0844 * @note Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed 0845 * several input buffers back-to-back to the Peripheral that will yield a single 0846 * HASH signature once all buffers have been entered. Wrap-up of input 0847 * buffers feeding and retrieval of digest is done by a call to 0848 * HAL_HASH_SHA1_Accmlt_End(). 0849 * @note Field hhash->Phase of HASH handle is tested to check whether or not 0850 * the Peripheral has already been initialized. 0851 * @note Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End() 0852 * to read it, feeding at the same time the last input buffer to the Peripheral. 0853 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 0854 * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able 0855 * to manage the ending buffer with a length in bytes not a multiple of 4. 0856 * @param hhash HASH handle. 0857 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0858 * @param Size length of the input buffer in bytes, must be a multiple of 4. 0859 * @retval HAL status 0860 */ 0861 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 0862 { 0863 return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); 0864 } 0865 0866 /** 0867 * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API. 0868 * @note Digest is available in pOutBuffer. 0869 * @param hhash HASH handle. 0870 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0871 * @param Size length of the input buffer in bytes. 0872 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 0873 * @param Timeout Timeout value 0874 * @retval HAL status 0875 */ 0876 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 0877 uint8_t *pOutBuffer, uint32_t Timeout) 0878 { 0879 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); 0880 } 0881 0882 /** 0883 * @} 0884 */ 0885 0886 /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode 0887 * @ingroup RTEMSBSPsARMSTM32H7 0888 * @brief HASH processing functions using interrupt mode. 0889 * 0890 @verbatim 0891 =============================================================================== 0892 ##### Interruption mode HASH processing functions ##### 0893 =============================================================================== 0894 [..] This section provides functions allowing to calculate in interrupt mode 0895 the hash value using one of the following algorithms: 0896 (+) MD5 0897 (++) HAL_HASH_MD5_Start_IT() 0898 (++) HAL_HASH_MD5_Accmlt_IT() 0899 (++) HAL_HASH_MD5_Accmlt_End_IT() 0900 (+) SHA1 0901 (++) HAL_HASH_SHA1_Start_IT() 0902 (++) HAL_HASH_SHA1_Accmlt_IT() 0903 (++) HAL_HASH_SHA1_Accmlt_End_IT() 0904 0905 [..] API HAL_HASH_IRQHandler() manages each HASH interruption. 0906 0907 [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in 0908 HMAC processing mode. 0909 0910 0911 @endverbatim 0912 * @{ 0913 */ 0914 0915 /** 0916 * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then 0917 * read the computed digest in interruption mode. 0918 * @note Digest is available in pOutBuffer. 0919 * @param hhash HASH handle. 0920 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0921 * @param Size length of the input buffer in bytes. 0922 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 0923 * @retval HAL status 0924 */ 0925 HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 0926 uint8_t *pOutBuffer) 0927 { 0928 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5); 0929 } 0930 0931 /** 0932 * @brief If not already done, initialize the HASH peripheral in MD5 mode then 0933 * processes pInBuffer in interruption mode. 0934 * @note Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed 0935 * several input buffers back-to-back to the Peripheral that will yield a single 0936 * HASH signature once all buffers have been entered. Wrap-up of input 0937 * buffers feeding and retrieval of digest is done by a call to 0938 * HAL_HASH_MD5_Accmlt_End_IT(). 0939 * @note Field hhash->Phase of HASH handle is tested to check whether or not 0940 * the Peripheral has already been initialized. 0941 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 0942 * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able 0943 * to manage the ending buffer with a length in bytes not a multiple of 4. 0944 * @param hhash HASH handle. 0945 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0946 * @param Size length of the input buffer in bytes, must be a multiple of 4. 0947 * @retval HAL status 0948 */ 0949 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 0950 { 0951 return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); 0952 } 0953 0954 /** 0955 * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API. 0956 * @note Digest is available in pOutBuffer. 0957 * @param hhash HASH handle. 0958 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0959 * @param Size length of the input buffer in bytes. 0960 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 0961 * @retval HAL status 0962 */ 0963 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 0964 uint8_t *pOutBuffer) 0965 { 0966 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5); 0967 } 0968 0969 /** 0970 * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then 0971 * read the computed digest in interruption mode. 0972 * @note Digest is available in pOutBuffer. 0973 * @param hhash HASH handle. 0974 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 0975 * @param Size length of the input buffer in bytes. 0976 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 0977 * @retval HAL status 0978 */ 0979 HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 0980 uint8_t *pOutBuffer) 0981 { 0982 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1); 0983 } 0984 0985 0986 /** 0987 * @brief If not already done, initialize the HASH peripheral in SHA1 mode then 0988 * processes pInBuffer in interruption mode. 0989 * @note Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed 0990 * several input buffers back-to-back to the Peripheral that will yield a single 0991 * HASH signature once all buffers have been entered. Wrap-up of input 0992 * buffers feeding and retrieval of digest is done by a call to 0993 * HAL_HASH_SHA1_Accmlt_End_IT(). 0994 * @note Field hhash->Phase of HASH handle is tested to check whether or not 0995 * the Peripheral has already been initialized. 0996 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 0997 * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able 0998 * to manage the ending buffer with a length in bytes not a multiple of 4. 0999 * @param hhash HASH handle. 1000 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1001 * @param Size length of the input buffer in bytes, must be a multiple of 4. 1002 * @retval HAL status 1003 */ 1004 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 1005 { 1006 return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); 1007 } 1008 1009 /** 1010 * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API. 1011 * @note Digest is available in pOutBuffer. 1012 * @param hhash HASH handle. 1013 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1014 * @param Size length of the input buffer in bytes. 1015 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 1016 * @retval HAL status 1017 */ 1018 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 1019 uint8_t *pOutBuffer) 1020 { 1021 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1); 1022 } 1023 1024 /** 1025 * @brief Handle HASH interrupt request. 1026 * @param hhash HASH handle. 1027 * @note HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well. 1028 * @note In case of error reported during the HASH interruption processing, 1029 * HAL_HASH_ErrorCallback() API is called so that user code can 1030 * manage the error. The error type is available in hhash->Status field. 1031 * @retval None 1032 */ 1033 void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash) 1034 { 1035 hhash->Status = HASH_IT(hhash); 1036 if (hhash->Status != HAL_OK) 1037 { 1038 hhash->ErrorCode |= HAL_HASH_ERROR_IT; 1039 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 1040 hhash->ErrorCallback(hhash); 1041 #else 1042 HAL_HASH_ErrorCallback(hhash); 1043 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 1044 /* After error handling by code user, reset HASH handle HAL status */ 1045 hhash->Status = HAL_OK; 1046 } 1047 } 1048 1049 /** 1050 * @} 1051 */ 1052 1053 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode 1054 * @ingroup RTEMSBSPsARMSTM32H7 1055 * @brief HASH processing functions using DMA mode. 1056 * 1057 @verbatim 1058 =============================================================================== 1059 ##### DMA mode HASH processing functions ##### 1060 =============================================================================== 1061 [..] This section provides functions allowing to calculate in DMA mode 1062 the hash value using one of the following algorithms: 1063 (+) MD5 1064 (++) HAL_HASH_MD5_Start_DMA() 1065 (++) HAL_HASH_MD5_Finish() 1066 (+) SHA1 1067 (++) HAL_HASH_SHA1_Start_DMA() 1068 (++) HAL_HASH_SHA1_Finish() 1069 1070 [..] When resorting to DMA mode to enter the data in the Peripheral, user must resort 1071 to HAL_HASH_xxx_Start_DMA() then read the resulting digest with 1072 HAL_HASH_xxx_Finish(). 1073 [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before 1074 the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be 1075 reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally 1076 retrieved thanks to HAL_HASH_xxx_Finish(). 1077 1078 @endverbatim 1079 * @{ 1080 */ 1081 1082 /** 1083 * @brief Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer 1084 * to feed the input buffer to the Peripheral. 1085 * @note Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must 1086 * be called to retrieve the computed digest. 1087 * @param hhash HASH handle. 1088 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1089 * @param Size length of the input buffer in bytes. 1090 * @retval HAL status 1091 */ 1092 HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 1093 { 1094 return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); 1095 } 1096 1097 /** 1098 * @brief Return the computed digest in MD5 mode. 1099 * @note The API waits for DCIS to be set then reads the computed digest. 1100 * @note HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in 1101 * HMAC MD5 mode. 1102 * @param hhash HASH handle. 1103 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 1104 * @param Timeout Timeout value. 1105 * @retval HAL status 1106 */ 1107 HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) 1108 { 1109 return HASH_Finish(hhash, pOutBuffer, Timeout); 1110 } 1111 1112 /** 1113 * @brief Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer 1114 * to feed the input buffer to the Peripheral. 1115 * @note Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must 1116 * be called to retrieve the computed digest. 1117 * @param hhash HASH handle. 1118 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1119 * @param Size length of the input buffer in bytes. 1120 * @retval HAL status 1121 */ 1122 HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 1123 { 1124 return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); 1125 } 1126 1127 1128 /** 1129 * @brief Return the computed digest in SHA1 mode. 1130 * @note The API waits for DCIS to be set then reads the computed digest. 1131 * @note HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in 1132 * HMAC SHA1 mode. 1133 * @param hhash HASH handle. 1134 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 1135 * @param Timeout Timeout value. 1136 * @retval HAL status 1137 */ 1138 HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) 1139 { 1140 return HASH_Finish(hhash, pOutBuffer, Timeout); 1141 } 1142 1143 /** 1144 * @} 1145 */ 1146 1147 /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode 1148 * @ingroup RTEMSBSPsARMSTM32H7 1149 * @brief HMAC processing functions using polling mode. 1150 * 1151 @verbatim 1152 =============================================================================== 1153 ##### Polling mode HMAC processing functions ##### 1154 =============================================================================== 1155 [..] This section provides functions allowing to calculate in polling mode 1156 the HMAC value using one of the following algorithms: 1157 (+) MD5 1158 (++) HAL_HMAC_MD5_Start() 1159 (+) SHA1 1160 (++) HAL_HMAC_SHA1_Start() 1161 1162 1163 @endverbatim 1164 * @{ 1165 */ 1166 1167 /** 1168 * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then 1169 * read the computed digest. 1170 * @note Digest is available in pOutBuffer. 1171 * @note Same key is used for the inner and the outer hash functions; pointer to key and 1172 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 1173 * @param hhash HASH handle. 1174 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1175 * @param Size length of the input buffer in bytes. 1176 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 1177 * @param Timeout Timeout value. 1178 * @retval HAL status 1179 */ 1180 HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 1181 uint32_t Timeout) 1182 { 1183 return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); 1184 } 1185 1186 /** 1187 * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then 1188 * read the computed digest. 1189 * @note Digest is available in pOutBuffer. 1190 * @note Same key is used for the inner and the outer hash functions; pointer to key and 1191 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 1192 * @param hhash HASH handle. 1193 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1194 * @param Size length of the input buffer in bytes. 1195 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 1196 * @param Timeout Timeout value. 1197 * @retval HAL status 1198 */ 1199 HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 1200 uint32_t Timeout) 1201 { 1202 return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); 1203 } 1204 1205 /** 1206 * @} 1207 */ 1208 1209 1210 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode 1211 * @ingroup RTEMSBSPsARMSTM32H7 1212 * @brief HMAC processing functions using interrupt mode. 1213 * 1214 @verbatim 1215 =============================================================================== 1216 ##### Interrupt mode HMAC processing functions ##### 1217 =============================================================================== 1218 [..] This section provides functions allowing to calculate in interrupt mode 1219 the HMAC value using one of the following algorithms: 1220 (+) MD5 1221 (++) HAL_HMAC_MD5_Start_IT() 1222 (+) SHA1 1223 (++) HAL_HMAC_SHA1_Start_IT() 1224 1225 @endverbatim 1226 * @{ 1227 */ 1228 1229 1230 /** 1231 * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then 1232 * read the computed digest in interrupt mode. 1233 * @note Digest is available in pOutBuffer. 1234 * @note Same key is used for the inner and the outer hash functions; pointer to key and 1235 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 1236 * @param hhash HASH handle. 1237 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1238 * @param Size length of the input buffer in bytes. 1239 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 1240 * @retval HAL status 1241 */ 1242 HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 1243 uint8_t *pOutBuffer) 1244 { 1245 return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5); 1246 } 1247 1248 /** 1249 * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then 1250 * read the computed digest in interrupt mode. 1251 * @note Digest is available in pOutBuffer. 1252 * @note Same key is used for the inner and the outer hash functions; pointer to key and 1253 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 1254 * @param hhash HASH handle. 1255 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1256 * @param Size length of the input buffer in bytes. 1257 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 1258 * @retval HAL status 1259 */ 1260 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 1261 uint8_t *pOutBuffer) 1262 { 1263 return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1); 1264 } 1265 1266 /** 1267 * @} 1268 */ 1269 1270 1271 1272 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode 1273 * @ingroup RTEMSBSPsARMSTM32H7 1274 * @brief HMAC processing functions using DMA modes. 1275 * 1276 @verbatim 1277 =============================================================================== 1278 ##### DMA mode HMAC processing functions ##### 1279 =============================================================================== 1280 [..] This section provides functions allowing to calculate in DMA mode 1281 the HMAC value using one of the following algorithms: 1282 (+) MD5 1283 (++) HAL_HMAC_MD5_Start_DMA() 1284 (+) SHA1 1285 (++) HAL_HMAC_SHA1_Start_DMA() 1286 1287 [..] When resorting to DMA mode to enter the data in the Peripheral for HMAC processing, 1288 user must resort to HAL_HMAC_xxx_Start_DMA() then read the resulting digest 1289 with HAL_HASH_xxx_Finish(). 1290 1291 @endverbatim 1292 * @{ 1293 */ 1294 1295 1296 /** 1297 * @brief Initialize the HASH peripheral in HMAC MD5 mode then initiate the required 1298 * DMA transfers to feed the key and the input buffer to the Peripheral. 1299 * @note Once the DMA transfers are finished (indicated by hhash->State set back 1300 * to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve 1301 * the computed digest. 1302 * @note Same key is used for the inner and the outer hash functions; pointer to key and 1303 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 1304 * @note If MDMAT bit is set before calling this function (multi-buffer 1305 * HASH processing case), the input buffer size (in bytes) must be 1306 * a multiple of 4 otherwise, the HASH digest computation is corrupted. 1307 * For the processing of the last buffer of the thread, MDMAT bit must 1308 * be reset and the buffer length (in bytes) doesn't have to be a 1309 * multiple of 4. 1310 * @param hhash HASH handle. 1311 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1312 * @param Size length of the input buffer in bytes. 1313 * @retval HAL status 1314 */ 1315 HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 1316 { 1317 return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); 1318 } 1319 1320 1321 /** 1322 * @brief Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required 1323 * DMA transfers to feed the key and the input buffer to the Peripheral. 1324 * @note Once the DMA transfers are finished (indicated by hhash->State set back 1325 * to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve 1326 * the computed digest. 1327 * @note Same key is used for the inner and the outer hash functions; pointer to key and 1328 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 1329 * @note If MDMAT bit is set before calling this function (multi-buffer 1330 * HASH processing case), the input buffer size (in bytes) must be 1331 * a multiple of 4 otherwise, the HASH digest computation is corrupted. 1332 * For the processing of the last buffer of the thread, MDMAT bit must 1333 * be reset and the buffer length (in bytes) doesn't have to be a 1334 * multiple of 4. 1335 * @param hhash HASH handle. 1336 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 1337 * @param Size length of the input buffer in bytes. 1338 * @retval HAL status 1339 */ 1340 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 1341 { 1342 return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); 1343 } 1344 1345 /** 1346 * @} 1347 */ 1348 1349 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions 1350 * @ingroup RTEMSBSPsARMSTM32H7 1351 * @brief Peripheral State functions. 1352 * 1353 @verbatim 1354 =============================================================================== 1355 ##### Peripheral State methods ##### 1356 =============================================================================== 1357 [..] 1358 This section permits to get in run-time the state and the peripheral handle 1359 status of the peripheral: 1360 (+) HAL_HASH_GetState() 1361 (+) HAL_HASH_GetStatus() 1362 1363 [..] 1364 Additionally, this subsection provides functions allowing to save and restore 1365 the HASH or HMAC processing context in case of calculation suspension: 1366 (+) HAL_HASH_ContextSaving() 1367 (+) HAL_HASH_ContextRestoring() 1368 1369 [..] 1370 This subsection provides functions allowing to suspend the HASH processing 1371 (+) when input are fed to the Peripheral by software 1372 (++) HAL_HASH_SwFeed_ProcessSuspend() 1373 (+) when input are fed to the Peripheral by DMA 1374 (++) HAL_HASH_DMAFeed_ProcessSuspend() 1375 1376 1377 1378 @endverbatim 1379 * @{ 1380 */ 1381 1382 /** 1383 * @brief Return the HASH handle state. 1384 * @note The API yields the current state of the handle (BUSY, READY,...). 1385 * @param hhash HASH handle. 1386 * @retval HAL HASH state 1387 */ 1388 HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash) 1389 { 1390 return hhash->State; 1391 } 1392 1393 1394 /** 1395 * @brief Return the HASH HAL status. 1396 * @note The API yields the HAL status of the handle: it is the result of the 1397 * latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT). 1398 * @param hhash HASH handle. 1399 * @retval HAL status 1400 */ 1401 HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash) 1402 { 1403 return hhash->Status; 1404 } 1405 1406 /** 1407 * @brief Save the HASH context in case of processing suspension. 1408 * @param hhash HASH handle. 1409 * @param pMemBuffer pointer to the memory buffer where the HASH context 1410 * is saved. 1411 * @note The IMR, STR, CR then all the CSR registers are saved 1412 * in that order. Only the r/w bits are read to be restored later on. 1413 * @note By default, all the context swap registers (there are 1414 * HASH_NUMBER_OF_CSR_REGISTERS of those) are saved. 1415 * @note pMemBuffer points to a buffer allocated by the user. The buffer size 1416 * must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long. 1417 * @retval None 1418 */ 1419 void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer) 1420 { 1421 uint32_t mem_ptr = (uint32_t)pMemBuffer; 1422 uint32_t csr_ptr = (uint32_t)HASH->CSR; 1423 uint32_t i; 1424 1425 /* Prevent unused argument(s) compilation warning */ 1426 UNUSED(hhash); 1427 1428 /* Save IMR register content */ 1429 *(uint32_t *)(mem_ptr) = READ_BIT(HASH->IMR, HASH_IT_DINI | HASH_IT_DCI); 1430 mem_ptr += 4U; 1431 /* Save STR register content */ 1432 *(uint32_t *)(mem_ptr) = READ_BIT(HASH->STR, HASH_STR_NBLW); 1433 mem_ptr += 4U; 1434 /* Save CR register content */ 1435 *(uint32_t *)(mem_ptr) = READ_BIT(HASH->CR, HASH_CR_DMAE | HASH_CR_DATATYPE | HASH_CR_MODE | HASH_CR_ALGO | 1436 HASH_CR_LKEY | HASH_CR_MDMAT); 1437 mem_ptr += 4U; 1438 /* By default, save all CSRs registers */ 1439 for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--) 1440 { 1441 *(uint32_t *)(mem_ptr) = *(uint32_t *)(csr_ptr); 1442 mem_ptr += 4U; 1443 csr_ptr += 4U; 1444 } 1445 } 1446 1447 1448 /** 1449 * @brief Restore the HASH context in case of processing resumption. 1450 * @param hhash HASH handle. 1451 * @param pMemBuffer pointer to the memory buffer where the HASH context 1452 * is stored. 1453 * @note The IMR, STR, CR then all the CSR registers are restored 1454 * in that order. Only the r/w bits are restored. 1455 * @note By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS 1456 * of those) are restored (all of them have been saved by default 1457 * beforehand). 1458 * @retval None 1459 */ 1460 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer) 1461 { 1462 uint32_t mem_ptr = (uint32_t)pMemBuffer; 1463 uint32_t csr_ptr = (uint32_t)HASH->CSR; 1464 uint32_t i; 1465 1466 /* Prevent unused argument(s) compilation warning */ 1467 UNUSED(hhash); 1468 1469 /* Restore IMR register content */ 1470 WRITE_REG(HASH->IMR, (*(uint32_t *)(mem_ptr))); 1471 mem_ptr += 4U; 1472 /* Restore STR register content */ 1473 WRITE_REG(HASH->STR, (*(uint32_t *)(mem_ptr))); 1474 mem_ptr += 4U; 1475 /* Restore CR register content */ 1476 WRITE_REG(HASH->CR, (*(uint32_t *)(mem_ptr))); 1477 mem_ptr += 4U; 1478 1479 /* Reset the HASH processor before restoring the Context 1480 Swap Registers (CSR) */ 1481 __HAL_HASH_INIT(); 1482 1483 /* By default, restore all CSR registers */ 1484 for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--) 1485 { 1486 WRITE_REG((*(uint32_t *)(csr_ptr)), (*(uint32_t *)(mem_ptr))); 1487 mem_ptr += 4U; 1488 csr_ptr += 4U; 1489 } 1490 } 1491 1492 1493 /** 1494 * @brief Initiate HASH processing suspension when in polling or interruption mode. 1495 * @param hhash HASH handle. 1496 * @note Set the handle field SuspendRequest to the appropriate value so that 1497 * the on-going HASH processing is suspended as soon as the required 1498 * conditions are met. Note that the actual suspension is carried out 1499 * by the functions HASH_WriteData() in polling mode and HASH_IT() in 1500 * interruption mode. 1501 * @retval None 1502 */ 1503 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) 1504 { 1505 /* Set Handle Suspend Request field */ 1506 hhash->SuspendRequest = HAL_HASH_SUSPEND; 1507 } 1508 1509 /** 1510 * @brief Suspend the HASH processing when in DMA mode. 1511 * @param hhash HASH handle. 1512 * @note When suspension attempt occurs at the very end of a DMA transfer and 1513 * all the data have already been entered in the Peripheral, hhash->State is 1514 * set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is 1515 * recommended to wrap-up the processing in reading the digest as usual. 1516 * @retval HAL status 1517 */ 1518 HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) 1519 { 1520 uint32_t tmp_remaining_DMATransferSize_inWords; 1521 uint32_t tmp_initial_DMATransferSize_inWords; 1522 uint32_t tmp_words_already_pushed; 1523 1524 if (hhash->State == HAL_HASH_STATE_READY) 1525 { 1526 return HAL_ERROR; 1527 } 1528 else 1529 { 1530 1531 /* Make sure there is enough time to suspend the processing */ 1532 tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR; 1533 1534 if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT) 1535 { 1536 /* No suspension attempted since almost to the end of the transferred data. */ 1537 /* Best option for user code is to wrap up low priority message hashing */ 1538 return HAL_ERROR; 1539 } 1540 1541 /* Wait for BUSY flag to be reset */ 1542 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 1543 { 1544 return HAL_TIMEOUT; 1545 } 1546 1547 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET) 1548 { 1549 return HAL_ERROR; 1550 } 1551 1552 /* Wait for BUSY flag to be set */ 1553 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK) 1554 { 1555 return HAL_TIMEOUT; 1556 } 1557 /* Disable DMA channel */ 1558 /* Note that the Abort function will 1559 - Clear the transfer error flags 1560 - Unlock 1561 - Set the State 1562 */ 1563 if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK) 1564 { 1565 return HAL_ERROR; 1566 } 1567 1568 /* Clear DMAE bit */ 1569 CLEAR_BIT(HASH->CR, HASH_CR_DMAE); 1570 1571 /* Wait for BUSY flag to be reset */ 1572 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 1573 { 1574 return HAL_TIMEOUT; 1575 } 1576 1577 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET) 1578 { 1579 return HAL_ERROR; 1580 } 1581 1582 /* At this point, DMA interface is disabled and no transfer is on-going */ 1583 /* Retrieve from the DMA handle how many words remain to be written */ 1584 tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR; 1585 1586 if (tmp_remaining_DMATransferSize_inWords == 0U) 1587 { 1588 /* All the DMA transfer is actually done. Suspension occurred at the very end 1589 of the transfer. Either the digest computation is about to start (HASH case) 1590 or processing is about to move from one step to another (HMAC case). 1591 In both cases, the processing can't be suspended at this point. It is 1592 safer to 1593 - retrieve the low priority block digest before starting the high 1594 priority block processing (HASH case) 1595 - re-attempt a new suspension (HMAC case) 1596 */ 1597 return HAL_ERROR; 1598 } 1599 else 1600 { 1601 1602 /* Compute how many words were supposed to be transferred by DMA */ 1603 tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount % 4U) != 0U) ? \ 1604 ((hhash->HashInCount + 3U) / 4U) : (hhash->HashInCount / 4U)); 1605 1606 /* If discrepancy between the number of words reported by DMA Peripheral and 1607 the numbers of words entered as reported by HASH Peripheral, correct it */ 1608 /* tmp_words_already_pushed reflects the number of words that were already pushed before 1609 the start of DMA transfer (multi-buffer processing case) */ 1610 tmp_words_already_pushed = hhash->NbWordsAlreadyPushed; 1611 if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - \ 1612 tmp_remaining_DMATransferSize_inWords) % 16U) != HASH_NBW_PUSHED()) 1613 { 1614 tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */ 1615 } 1616 1617 /* Accordingly, update the input pointer that points at the next word to be 1618 transferred to the Peripheral by DMA */ 1619 hhash->pHashInBuffPtr += 4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ; 1620 1621 /* And store in HashInCount the remaining size to transfer (in bytes) */ 1622 hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords; 1623 1624 } 1625 1626 /* Set State as suspended */ 1627 hhash->State = HAL_HASH_STATE_SUSPENDED; 1628 1629 return HAL_OK; 1630 1631 } 1632 } 1633 1634 /** 1635 * @brief Return the HASH handle error code. 1636 * @param hhash pointer to a HASH_HandleTypeDef structure. 1637 * @retval HASH Error Code 1638 */ 1639 uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash) 1640 { 1641 /* Return HASH Error Code */ 1642 return hhash->ErrorCode; 1643 } 1644 /** 1645 * @} 1646 */ 1647 1648 1649 /** 1650 * @} 1651 */ 1652 1653 /** @defgroup HASH_Private_Functions HASH Private Functions 1654 * @ingroup RTEMSBSPsARMSTM32H7 1655 * @{ 1656 */ 1657 1658 /** 1659 * @brief DMA HASH Input Data transfer completion callback. 1660 * @param hdma DMA handle. 1661 * @note In case of HMAC processing, HASH_DMAXferCplt() initiates 1662 * the next DMA transfer for the following HMAC step. 1663 * @retval None 1664 */ 1665 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma) 1666 { 1667 HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 1668 uint32_t inputaddr; 1669 uint32_t buffersize; 1670 HAL_StatusTypeDef status; 1671 1672 if (hhash->State != HAL_HASH_STATE_SUSPENDED) 1673 { 1674 1675 /* Disable the DMA transfer */ 1676 CLEAR_BIT(HASH->CR, HASH_CR_DMAE); 1677 1678 if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U) 1679 { 1680 /* If no HMAC processing, input data transfer is now over */ 1681 1682 /* Change the HASH state to ready */ 1683 hhash->State = HAL_HASH_STATE_READY; 1684 1685 /* Call Input data transfer complete call back */ 1686 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 1687 hhash->InCpltCallback(hhash); 1688 #else 1689 HAL_HASH_InCpltCallback(hhash); 1690 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 1691 1692 } 1693 else 1694 { 1695 /* HMAC processing: depending on the current HMAC step and whether or 1696 not multi-buffer processing is on-going, the next step is initiated 1697 and MDMAT bit is set. */ 1698 1699 1700 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3) 1701 { 1702 /* This is the end of HMAC processing */ 1703 1704 /* Change the HASH state to ready */ 1705 hhash->State = HAL_HASH_STATE_READY; 1706 1707 /* Call Input data transfer complete call back 1708 (note that the last DMA transfer was that of the key 1709 for the outer HASH operation). */ 1710 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 1711 hhash->InCpltCallback(hhash); 1712 #else 1713 HAL_HASH_InCpltCallback(hhash); 1714 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 1715 1716 return; 1717 } 1718 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) 1719 { 1720 inputaddr = (uint32_t)hhash->pHashMsgBuffPtr; /* DMA transfer start address */ 1721 buffersize = hhash->HashBuffSize; /* DMA transfer size (in bytes) */ 1722 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */ 1723 1724 /* In case of suspension request, save the new starting parameters */ 1725 hhash->HashInCount = hhash->HashBuffSize; /* Initial DMA transfer size (in bytes) */ 1726 hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr ; /* DMA transfer start address */ 1727 1728 hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */ 1729 /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */ 1730 if (hhash->DigestCalculationDisable != RESET) 1731 { 1732 /* Digest calculation is disabled: Step 2 must start with MDMAT bit set, 1733 no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */ 1734 __HAL_HASH_SET_MDMAT(); 1735 } 1736 } 1737 else /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/ 1738 { 1739 if (hhash->DigestCalculationDisable != RESET) 1740 { 1741 /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral 1742 (case of multi-buffer HMAC processing): 1743 DCAL must not be set. 1744 Phase remains in Step 2, MDMAT remains set at this point. 1745 Change the HASH state to ready and call Input data transfer complete call back. */ 1746 hhash->State = HAL_HASH_STATE_READY; 1747 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 1748 hhash->InCpltCallback(hhash); 1749 #else 1750 HAL_HASH_InCpltCallback(hhash); 1751 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 1752 return ; 1753 } 1754 else 1755 { 1756 /* Digest calculation is not disabled (case of single buffer input or last buffer 1757 of multi-buffer HMAC processing) */ 1758 inputaddr = (uint32_t)hhash->Init.pKey; /* DMA transfer start address */ 1759 buffersize = hhash->Init.KeySize; /* DMA transfer size (in bytes) */ 1760 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */ 1761 /* In case of suspension request, save the new starting parameters */ 1762 hhash->HashInCount = hhash->Init.KeySize; /* Initial size for second DMA transfer (input data) */ 1763 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* address passed to DMA, now entering data message */ 1764 1765 hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */ 1766 } 1767 } 1768 1769 /* Configure the Number of valid bits in last word of the message */ 1770 __HAL_HASH_SET_NBVALIDBITS(buffersize); 1771 1772 /* Set the HASH DMA transfer completion call back */ 1773 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; 1774 1775 /* Enable the DMA In DMA stream */ 1776 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \ 1777 (((buffersize % 4U) != 0U) ? ((buffersize + (4U - (buffersize % 4U))) / 4U) : \ 1778 (buffersize / 4U))); 1779 1780 /* Enable DMA requests */ 1781 SET_BIT(HASH->CR, HASH_CR_DMAE); 1782 1783 /* Return function status */ 1784 if (status != HAL_OK) 1785 { 1786 /* Update HASH state machine to error */ 1787 hhash->State = HAL_HASH_STATE_ERROR; 1788 } 1789 else 1790 { 1791 /* Change HASH state */ 1792 hhash->State = HAL_HASH_STATE_BUSY; 1793 } 1794 } 1795 } 1796 1797 return; 1798 } 1799 1800 /** 1801 * @brief DMA HASH communication error callback. 1802 * @param hdma DMA handle. 1803 * @note HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that 1804 * can contain user code to manage the error. 1805 * @retval None 1806 */ 1807 static void HASH_DMAError(DMA_HandleTypeDef *hdma) 1808 { 1809 HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 1810 1811 if (hhash->State != HAL_HASH_STATE_SUSPENDED) 1812 { 1813 hhash->ErrorCode |= HAL_HASH_ERROR_DMA; 1814 /* Set HASH state to ready to prevent any blocking issue in user code 1815 present in HAL_HASH_ErrorCallback() */ 1816 hhash->State = HAL_HASH_STATE_READY; 1817 /* Set HASH handle status to error */ 1818 hhash->Status = HAL_ERROR; 1819 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 1820 hhash->ErrorCallback(hhash); 1821 #else 1822 HAL_HASH_ErrorCallback(hhash); 1823 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 1824 /* After error handling by code user, reset HASH handle HAL status */ 1825 hhash->Status = HAL_OK; 1826 1827 } 1828 } 1829 1830 /** 1831 * @brief Feed the input buffer to the HASH Peripheral. 1832 * @param hhash HASH handle. 1833 * @param pInBuffer pointer to input buffer. 1834 * @param Size the size of input buffer in bytes. 1835 * @note HASH_WriteData() regularly reads hhash->SuspendRequest to check whether 1836 * or not the HASH processing must be suspended. If this is the case, the 1837 * processing is suspended when possible and the Peripheral feeding point reached at 1838 * suspension time is stored in the handle for resumption later on. 1839 * @retval HAL status 1840 */ 1841 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 1842 { 1843 uint32_t buffercounter; 1844 __IO uint32_t inputaddr = (uint32_t) pInBuffer; 1845 uint32_t tmp; 1846 1847 for (buffercounter = 0U; buffercounter < (Size / 4U); buffercounter++) 1848 { 1849 /* Write input data 4 bytes at a time */ 1850 HASH->DIN = *(uint32_t *)inputaddr; 1851 inputaddr += 4U; 1852 1853 /* If the suspension flag has been raised and if the processing is not about 1854 to end, suspend processing */ 1855 if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && (((buffercounter * 4U) + 4U) < Size)) 1856 { 1857 /* wait for flag BUSY not set before Wait for DINIS = 1*/ 1858 if ((buffercounter * 4U) >= 64U) 1859 { 1860 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 1861 { 1862 return HAL_TIMEOUT; 1863 } 1864 } 1865 /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free 1866 in the input buffer */ 1867 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) 1868 { 1869 /* Reset SuspendRequest */ 1870 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; 1871 1872 /* Depending whether the key or the input data were fed to the Peripheral, the feeding point 1873 reached at suspension time is not saved in the same handle fields */ 1874 if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)) 1875 { 1876 /* Save current reading and writing locations of Input and Output buffers */ 1877 hhash->pHashInBuffPtr = (uint8_t *)inputaddr; 1878 /* Save the number of bytes that remain to be processed at this point */ 1879 hhash->HashInCount = Size - ((buffercounter * 4U) + 4U); 1880 } 1881 else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)) 1882 { 1883 /* Save current reading and writing locations of Input and Output buffers */ 1884 hhash->pHashKeyBuffPtr = (uint8_t *)inputaddr; 1885 /* Save the number of bytes that remain to be processed at this point */ 1886 hhash->HashKeyCount = Size - ((buffercounter * 4U) + 4U); 1887 } 1888 else 1889 { 1890 /* Unexpected phase: unlock process and report error */ 1891 hhash->State = HAL_HASH_STATE_READY; 1892 __HAL_UNLOCK(hhash); 1893 return HAL_ERROR; 1894 } 1895 1896 /* Set the HASH state to Suspended and exit to stop entering data */ 1897 hhash->State = HAL_HASH_STATE_SUSPENDED; 1898 1899 return HAL_OK; 1900 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) */ 1901 } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */ 1902 } /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4) */ 1903 1904 /* At this point, all the data have been entered to the Peripheral: exit */ 1905 1906 if ((Size % 4U) != 0U) 1907 { 1908 if (hhash->Init.DataType == HASH_DATATYPE_16B) 1909 { 1910 /* Write remaining input data */ 1911 1912 if ((Size % 4U) <= 2U) 1913 { 1914 HASH->DIN = (uint32_t) * (uint16_t *)inputaddr; 1915 } 1916 if ((Size % 4U) == 3U) 1917 { 1918 HASH->DIN = *(uint32_t *)inputaddr; 1919 } 1920 1921 } 1922 else if ((hhash->Init.DataType == HASH_DATATYPE_8B) 1923 || (hhash->Init.DataType == HASH_DATATYPE_1B)) /* byte swap or bit swap or */ 1924 { 1925 /* Write remaining input data */ 1926 if ((Size % 4U) == 1U) 1927 { 1928 HASH->DIN = (uint32_t) * (uint8_t *)inputaddr; 1929 } 1930 if ((Size % 4U) == 2U) 1931 { 1932 HASH->DIN = (uint32_t) * (uint16_t *)inputaddr; 1933 } 1934 if ((Size % 4U) == 3U) 1935 { 1936 tmp = *(uint8_t *)inputaddr; 1937 tmp |= (uint32_t)*(uint8_t *)(inputaddr + 1U) << 8U; 1938 tmp |= (uint32_t)*(uint8_t *)(inputaddr + 2U) << 16U; 1939 HASH->DIN = tmp; 1940 } 1941 1942 } 1943 else 1944 { 1945 HASH->DIN = *(uint32_t *)inputaddr; 1946 } 1947 /*hhash->HashInCount += 4U;*/ 1948 } 1949 1950 1951 return HAL_OK; 1952 } 1953 1954 /** 1955 * @brief Retrieve the message digest. 1956 * @param pMsgDigest pointer to the computed digest. 1957 * @param Size message digest size in bytes. 1958 * @retval None 1959 */ 1960 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size) 1961 { 1962 uint32_t msgdigest = (uint32_t)pMsgDigest; 1963 1964 switch (Size) 1965 { 1966 /* Read the message digest */ 1967 case 16: /* MD5 */ 1968 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); 1969 msgdigest += 4U; 1970 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); 1971 msgdigest += 4U; 1972 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); 1973 msgdigest += 4U; 1974 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); 1975 break; 1976 case 20: /* SHA1 */ 1977 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); 1978 msgdigest += 4U; 1979 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); 1980 msgdigest += 4U; 1981 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); 1982 msgdigest += 4U; 1983 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); 1984 msgdigest += 4U; 1985 *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]); 1986 break; 1987 case 28: /* SHA224 */ 1988 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); 1989 msgdigest += 4U; 1990 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); 1991 msgdigest += 4U; 1992 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); 1993 msgdigest += 4U; 1994 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); 1995 msgdigest += 4U; 1996 *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]); 1997 msgdigest += 4U; 1998 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]); 1999 msgdigest += 4U; 2000 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]); 2001 break; 2002 case 32: /* SHA256 */ 2003 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); 2004 msgdigest += 4U; 2005 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); 2006 msgdigest += 4U; 2007 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); 2008 msgdigest += 4U; 2009 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); 2010 msgdigest += 4U; 2011 *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]); 2012 msgdigest += 4U; 2013 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]); 2014 msgdigest += 4U; 2015 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]); 2016 msgdigest += 4U; 2017 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[7]); 2018 break; 2019 default: 2020 break; 2021 } 2022 } 2023 2024 2025 2026 /** 2027 * @brief Handle HASH processing Timeout. 2028 * @param hhash HASH handle. 2029 * @param Flag specifies the HASH flag to check. 2030 * @param Status the Flag status (SET or RESET). 2031 * @param Timeout Timeout duration. 2032 * @retval HAL status 2033 */ 2034 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, 2035 uint32_t Timeout) 2036 { 2037 uint32_t tickstart = HAL_GetTick(); 2038 2039 /* Wait until flag is set */ 2040 if (Status == RESET) 2041 { 2042 while (__HAL_HASH_GET_FLAG(Flag) == RESET) 2043 { 2044 /* Check for the Timeout */ 2045 if (Timeout != HAL_MAX_DELAY) 2046 { 2047 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) 2048 { 2049 /* Set State to Ready to be able to restart later on */ 2050 hhash->State = HAL_HASH_STATE_READY; 2051 /* Store time out issue in handle status */ 2052 hhash->Status = HAL_TIMEOUT; 2053 2054 /* Process Unlocked */ 2055 __HAL_UNLOCK(hhash); 2056 2057 return HAL_TIMEOUT; 2058 } 2059 } 2060 } 2061 } 2062 else 2063 { 2064 while (__HAL_HASH_GET_FLAG(Flag) != RESET) 2065 { 2066 /* Check for the Timeout */ 2067 if (Timeout != HAL_MAX_DELAY) 2068 { 2069 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) 2070 { 2071 /* Set State to Ready to be able to restart later on */ 2072 hhash->State = HAL_HASH_STATE_READY; 2073 /* Store time out issue in handle status */ 2074 hhash->Status = HAL_TIMEOUT; 2075 2076 /* Process Unlocked */ 2077 __HAL_UNLOCK(hhash); 2078 2079 return HAL_TIMEOUT; 2080 } 2081 } 2082 } 2083 } 2084 return HAL_OK; 2085 } 2086 2087 2088 /** 2089 * @brief HASH processing in interruption mode. 2090 * @param hhash HASH handle. 2091 * @note HASH_IT() regularly reads hhash->SuspendRequest to check whether 2092 * or not the HASH processing must be suspended. If this is the case, the 2093 * processing is suspended when possible and the Peripheral feeding point reached at 2094 * suspension time is stored in the handle for resumption later on. 2095 * @retval HAL status 2096 */ 2097 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) 2098 { 2099 if (hhash->State == HAL_HASH_STATE_BUSY) 2100 { 2101 /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */ 2102 if (hhash->HashITCounter == 0U) 2103 { 2104 /* Disable Interrupts */ 2105 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 2106 /* HASH state set back to Ready to prevent any issue in user code 2107 present in HAL_HASH_ErrorCallback() */ 2108 hhash->State = HAL_HASH_STATE_READY; 2109 return HAL_ERROR; 2110 } 2111 else if (hhash->HashITCounter == 1U) 2112 { 2113 /* This is the first call to HASH_IT, the first input data are about to be 2114 entered in the Peripheral. A specific processing is carried out at this point to 2115 start-up the processing. */ 2116 hhash->HashITCounter = 2U; 2117 } 2118 else 2119 { 2120 /* Cruise speed reached, HashITCounter remains equal to 3 until the end of 2121 the HASH processing or the end of the current step for HMAC processing. */ 2122 hhash->HashITCounter = 3U; 2123 } 2124 2125 /* If digest is ready */ 2126 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS)) 2127 { 2128 /* Read the digest */ 2129 HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH()); 2130 2131 /* Disable Interrupts */ 2132 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 2133 /* Change the HASH state */ 2134 hhash->State = HAL_HASH_STATE_READY; 2135 /* Reset HASH state machine */ 2136 hhash->Phase = HAL_HASH_PHASE_READY; 2137 /* Call digest computation complete call back */ 2138 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 2139 hhash->DgstCpltCallback(hhash); 2140 #else 2141 HAL_HASH_DgstCpltCallback(hhash); 2142 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 2143 2144 return HAL_OK; 2145 } 2146 2147 /* If Peripheral ready to accept new data */ 2148 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) 2149 { 2150 2151 /* If the suspension flag has been raised and if the processing is not about 2152 to end, suspend processing */ 2153 if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND)) 2154 { 2155 /* Disable Interrupts */ 2156 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 2157 2158 /* Reset SuspendRequest */ 2159 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; 2160 2161 /* Change the HASH state */ 2162 hhash->State = HAL_HASH_STATE_SUSPENDED; 2163 2164 return HAL_OK; 2165 } 2166 2167 /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and 2168 check whether the digest calculation has been triggered */ 2169 if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) 2170 { 2171 /* Call Input data transfer complete call back 2172 (called at the end of each step for HMAC) */ 2173 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 2174 hhash->InCpltCallback(hhash); 2175 #else 2176 HAL_HASH_InCpltCallback(hhash); 2177 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 2178 2179 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) 2180 { 2181 /* Wait until Peripheral is not busy anymore */ 2182 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 2183 { 2184 /* Disable Interrupts */ 2185 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 2186 return HAL_TIMEOUT; 2187 } 2188 /* Initialization start for HMAC STEP 2 */ 2189 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */ 2190 __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); /* Set NBLW for the input message */ 2191 hhash->HashInCount = hhash->HashBuffSize; /* Set the input data size (in bytes) */ 2192 hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr; /* Set the input data address */ 2193 hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start 2194 of a new phase */ 2195 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */ 2196 } 2197 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) 2198 { 2199 /* Wait until Peripheral is not busy anymore */ 2200 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 2201 { 2202 /* Disable Interrupts */ 2203 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 2204 return HAL_TIMEOUT; 2205 } 2206 /* Initialization start for HMAC STEP 3 */ 2207 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */ 2208 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); /* Set NBLW for the key */ 2209 hhash->HashInCount = hhash->Init.KeySize; /* Set the key size (in bytes) */ 2210 hhash->pHashInBuffPtr = hhash->Init.pKey; /* Set the key address */ 2211 hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start 2212 of a new phase */ 2213 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */ 2214 } 2215 else 2216 { 2217 /* Nothing to do */ 2218 } 2219 } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */ 2220 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/ 2221 2222 /* Return function status */ 2223 return HAL_OK; 2224 } 2225 else 2226 { 2227 return HAL_BUSY; 2228 } 2229 } 2230 2231 2232 /** 2233 * @brief Write a block of data in HASH Peripheral in interruption mode. 2234 * @param hhash HASH handle. 2235 * @note HASH_Write_Block_Data() is called under interruption by HASH_IT(). 2236 * @retval HAL status 2237 */ 2238 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash) 2239 { 2240 uint32_t inputaddr; 2241 uint32_t buffercounter; 2242 uint32_t inputcounter; 2243 uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED; 2244 2245 /* If there are more than 64 bytes remaining to be entered */ 2246 if (hhash->HashInCount > 64U) 2247 { 2248 inputaddr = (uint32_t)hhash->pHashInBuffPtr; 2249 /* Write the Input block in the Data IN register 2250 (16 32-bit words, or 64 bytes are entered) */ 2251 for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U) 2252 { 2253 HASH->DIN = *(uint32_t *)inputaddr; 2254 inputaddr += 4U; 2255 } 2256 /* If this is the start of input data entering, an additional word 2257 must be entered to start up the HASH processing */ 2258 if (hhash->HashITCounter == 2U) 2259 { 2260 HASH->DIN = *(uint32_t *)inputaddr; 2261 if (hhash->HashInCount >= 68U) 2262 { 2263 /* There are still data waiting to be entered in the Peripheral. 2264 Decrement buffer counter and set pointer to the proper 2265 memory location for the next data entering round. */ 2266 hhash->HashInCount -= 68U; 2267 hhash->pHashInBuffPtr += 68U; 2268 } 2269 else 2270 { 2271 /* All the input buffer has been fed to the HW. */ 2272 hhash->HashInCount = 0U; 2273 } 2274 } 2275 else 2276 { 2277 /* 64 bytes have been entered and there are still some remaining: 2278 Decrement buffer counter and set pointer to the proper 2279 memory location for the next data entering round.*/ 2280 hhash->HashInCount -= 64U; 2281 hhash->pHashInBuffPtr += 64U; 2282 } 2283 } 2284 else 2285 { 2286 /* 64 or less bytes remain to be entered. This is the last 2287 data entering round. */ 2288 2289 /* Get the buffer address */ 2290 inputaddr = (uint32_t)hhash->pHashInBuffPtr; 2291 /* Get the buffer counter */ 2292 inputcounter = hhash->HashInCount; 2293 /* Disable Interrupts */ 2294 __HAL_HASH_DISABLE_IT(HASH_IT_DINI); 2295 2296 /* Write the Input block in the Data IN register */ 2297 for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++) 2298 { 2299 HASH->DIN = *(uint32_t *)inputaddr; 2300 inputaddr += 4U; 2301 } 2302 2303 if (hhash->Accumulation == 1U) 2304 { 2305 /* Field accumulation is set, API only feeds data to the Peripheral and under interruption. 2306 The digest computation will be started when the last buffer data are entered. */ 2307 2308 /* Reset multi buffers accumulation flag */ 2309 hhash->Accumulation = 0U; 2310 /* Change the HASH state */ 2311 hhash->State = HAL_HASH_STATE_READY; 2312 /* Call Input data transfer complete call back */ 2313 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 2314 hhash->InCpltCallback(hhash); 2315 #else 2316 HAL_HASH_InCpltCallback(hhash); 2317 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 2318 } 2319 else 2320 { 2321 /* Start the Digest calculation */ 2322 __HAL_HASH_START_DIGEST(); 2323 /* Return indication that digest calculation has started: 2324 this return value triggers the call to Input data transfer 2325 complete call back as well as the proper transition from 2326 one step to another in HMAC mode. */ 2327 ret = HASH_DIGEST_CALCULATION_STARTED; 2328 } 2329 /* Reset buffer counter */ 2330 hhash->HashInCount = 0; 2331 } 2332 2333 /* Return whether or digest calculation has started */ 2334 return ret; 2335 } 2336 2337 /** 2338 * @brief HMAC processing in polling mode. 2339 * @param hhash HASH handle. 2340 * @param Timeout Timeout value. 2341 * @retval HAL status 2342 */ 2343 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout) 2344 { 2345 /* Ensure first that Phase is correct */ 2346 if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2) 2347 && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3)) 2348 { 2349 /* Change the HASH state */ 2350 hhash->State = HAL_HASH_STATE_READY; 2351 2352 /* Process Unlock */ 2353 __HAL_UNLOCK(hhash); 2354 2355 /* Return function status */ 2356 return HAL_ERROR; 2357 } 2358 2359 /* HMAC Step 1 processing */ 2360 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) 2361 { 2362 /************************** STEP 1 ******************************************/ 2363 /* Configure the Number of valid bits in last word of the message */ 2364 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); 2365 2366 /* Write input buffer in Data register */ 2367 hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount); 2368 if (hhash->Status != HAL_OK) 2369 { 2370 return hhash->Status; 2371 } 2372 2373 /* Check whether or not key entering process has been suspended */ 2374 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 2375 { 2376 /* Process Unlocked */ 2377 __HAL_UNLOCK(hhash); 2378 2379 /* Stop right there and return function status */ 2380 return HAL_OK; 2381 } 2382 2383 /* No processing suspension at this point: set DCAL bit. */ 2384 __HAL_HASH_START_DIGEST(); 2385 2386 /* Wait for BUSY flag to be cleared */ 2387 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK) 2388 { 2389 return HAL_TIMEOUT; 2390 } 2391 2392 /* Move from Step 1 to Step 2 */ 2393 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; 2394 2395 } 2396 2397 /* HMAC Step 2 processing. 2398 After phase check, HMAC_Processing() may 2399 - directly start up from this point in resumption case 2400 if the same Step 2 processing was suspended previously 2401 - or fall through from the Step 1 processing carried out hereabove */ 2402 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) 2403 { 2404 /************************** STEP 2 ******************************************/ 2405 /* Configure the Number of valid bits in last word of the message */ 2406 __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); 2407 2408 /* Write input buffer in Data register */ 2409 hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount); 2410 if (hhash->Status != HAL_OK) 2411 { 2412 return hhash->Status; 2413 } 2414 2415 /* Check whether or not data entering process has been suspended */ 2416 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 2417 { 2418 /* Process Unlocked */ 2419 __HAL_UNLOCK(hhash); 2420 2421 /* Stop right there and return function status */ 2422 return HAL_OK; 2423 } 2424 2425 /* No processing suspension at this point: set DCAL bit. */ 2426 __HAL_HASH_START_DIGEST(); 2427 2428 /* Wait for BUSY flag to be cleared */ 2429 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK) 2430 { 2431 return HAL_TIMEOUT; 2432 } 2433 2434 /* Move from Step 2 to Step 3 */ 2435 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; 2436 /* In case Step 1 phase was suspended then resumed, 2437 set again Key input buffers and size before moving to 2438 next step */ 2439 hhash->pHashKeyBuffPtr = hhash->Init.pKey; 2440 hhash->HashKeyCount = hhash->Init.KeySize; 2441 } 2442 2443 2444 /* HMAC Step 3 processing. 2445 After phase check, HMAC_Processing() may 2446 - directly start up from this point in resumption case 2447 if the same Step 3 processing was suspended previously 2448 - or fall through from the Step 2 processing carried out hereabove */ 2449 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3) 2450 { 2451 /************************** STEP 3 ******************************************/ 2452 /* Configure the Number of valid bits in last word of the message */ 2453 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); 2454 2455 /* Write input buffer in Data register */ 2456 hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount); 2457 if (hhash->Status != HAL_OK) 2458 { 2459 return hhash->Status; 2460 } 2461 2462 /* Check whether or not key entering process has been suspended */ 2463 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 2464 { 2465 /* Process Unlocked */ 2466 __HAL_UNLOCK(hhash); 2467 2468 /* Stop right there and return function status */ 2469 return HAL_OK; 2470 } 2471 2472 /* No processing suspension at this point: start the Digest calculation. */ 2473 __HAL_HASH_START_DIGEST(); 2474 2475 /* Wait for DCIS flag to be set */ 2476 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) 2477 { 2478 return HAL_TIMEOUT; 2479 } 2480 2481 /* Read the message digest */ 2482 HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH()); 2483 2484 /* Reset HASH state machine */ 2485 hhash->Phase = HAL_HASH_PHASE_READY; 2486 } 2487 2488 /* Change the HASH state */ 2489 hhash->State = HAL_HASH_STATE_READY; 2490 2491 /* Process Unlock */ 2492 __HAL_UNLOCK(hhash); 2493 2494 /* Return function status */ 2495 return HAL_OK; 2496 } 2497 2498 2499 /** 2500 * @brief Initialize the HASH peripheral, next process pInBuffer then 2501 * read the computed digest. 2502 * @note Digest is available in pOutBuffer. 2503 * @param hhash HASH handle. 2504 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 2505 * @param Size length of the input buffer in bytes. 2506 * @param pOutBuffer pointer to the computed digest. 2507 * @param Timeout Timeout value. 2508 * @param Algorithm HASH algorithm. 2509 * @retval HAL status 2510 */ 2511 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 2512 uint32_t Timeout, uint32_t Algorithm) 2513 { 2514 uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */ 2515 uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */ 2516 HAL_HASH_StateTypeDef State_tmp = hhash->State; 2517 2518 2519 /* Initiate HASH processing in case of start or resumption */ 2520 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 2521 { 2522 /* Check input parameters */ 2523 if ((pInBuffer == NULL) || (pOutBuffer == NULL)) 2524 { 2525 hhash->State = HAL_HASH_STATE_READY; 2526 return HAL_ERROR; 2527 } 2528 2529 /* Process Locked */ 2530 __HAL_LOCK(hhash); 2531 2532 /* Check if initialization phase has not been already performed */ 2533 if (hhash->Phase == HAL_HASH_PHASE_READY) 2534 { 2535 /* Change the HASH state */ 2536 hhash->State = HAL_HASH_STATE_BUSY; 2537 2538 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 2539 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 2540 2541 /* Configure the number of valid bits in last word of the message */ 2542 __HAL_HASH_SET_NBVALIDBITS(Size); 2543 2544 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as 2545 input parameters of HASH_WriteData() */ 2546 pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */ 2547 Size_tmp = Size; /* Size_tmp contains the input data size in bytes */ 2548 2549 /* Set the phase */ 2550 hhash->Phase = HAL_HASH_PHASE_PROCESS; 2551 } 2552 else if (hhash->Phase == HAL_HASH_PHASE_PROCESS) 2553 { 2554 /* if the Peripheral has already been initialized, two cases are possible */ 2555 2556 /* Process resumption time ... */ 2557 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 2558 { 2559 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set 2560 to the API input parameters but to those saved beforehand by HASH_WriteData() 2561 when the processing was suspended */ 2562 pInBuffer_tmp = hhash->pHashInBuffPtr; 2563 Size_tmp = hhash->HashInCount; 2564 } 2565 /* ... or multi-buffer HASH processing end */ 2566 else 2567 { 2568 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as 2569 input parameters of HASH_WriteData() */ 2570 pInBuffer_tmp = pInBuffer; 2571 Size_tmp = Size; 2572 /* Configure the number of valid bits in last word of the message */ 2573 __HAL_HASH_SET_NBVALIDBITS(Size); 2574 } 2575 /* Change the HASH state */ 2576 hhash->State = HAL_HASH_STATE_BUSY; 2577 } 2578 else 2579 { 2580 /* Phase error */ 2581 hhash->State = HAL_HASH_STATE_READY; 2582 2583 /* Process Unlocked */ 2584 __HAL_UNLOCK(hhash); 2585 2586 /* Return function status */ 2587 return HAL_ERROR; 2588 } 2589 2590 2591 /* Write input buffer in Data register */ 2592 hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp); 2593 if (hhash->Status != HAL_OK) 2594 { 2595 return hhash->Status; 2596 } 2597 2598 /* If the process has not been suspended, carry on to digest calculation */ 2599 if (hhash->State != HAL_HASH_STATE_SUSPENDED) 2600 { 2601 /* Start the Digest calculation */ 2602 __HAL_HASH_START_DIGEST(); 2603 2604 /* Wait for DCIS flag to be set */ 2605 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) 2606 { 2607 return HAL_TIMEOUT; 2608 } 2609 2610 /* Read the message digest */ 2611 HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH()); 2612 2613 /* Change the HASH state */ 2614 hhash->State = HAL_HASH_STATE_READY; 2615 2616 /* Reset HASH state machine */ 2617 hhash->Phase = HAL_HASH_PHASE_READY; 2618 2619 } 2620 2621 /* Process Unlocked */ 2622 __HAL_UNLOCK(hhash); 2623 2624 /* Return function status */ 2625 return HAL_OK; 2626 2627 } 2628 else 2629 { 2630 return HAL_BUSY; 2631 } 2632 } 2633 2634 2635 /** 2636 * @brief If not already done, initialize the HASH peripheral then 2637 * processes pInBuffer. 2638 * @note Field hhash->Phase of HASH handle is tested to check whether or not 2639 * the Peripheral has already been initialized. 2640 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 2641 * HASH digest computation is corrupted. 2642 * @param hhash HASH handle. 2643 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 2644 * @param Size length of the input buffer in bytes, must be a multiple of 4. 2645 * @param Algorithm HASH algorithm. 2646 * @retval HAL status 2647 */ 2648 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) 2649 { 2650 uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */ 2651 uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */ 2652 HAL_HASH_StateTypeDef State_tmp = hhash->State; 2653 2654 /* Make sure the input buffer size (in bytes) is a multiple of 4 */ 2655 if ((Size % 4U) != 0U) 2656 { 2657 return HAL_ERROR; 2658 } 2659 2660 /* Initiate HASH processing in case of start or resumption */ 2661 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 2662 { 2663 /* Check input parameters */ 2664 if ((pInBuffer == NULL) || (Size == 0U)) 2665 { 2666 hhash->State = HAL_HASH_STATE_READY; 2667 return HAL_ERROR; 2668 } 2669 2670 /* Process Locked */ 2671 __HAL_LOCK(hhash); 2672 2673 /* If resuming the HASH processing */ 2674 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 2675 { 2676 /* Change the HASH state */ 2677 hhash->State = HAL_HASH_STATE_BUSY; 2678 2679 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set 2680 to the API input parameters but to those saved beforehand by HASH_WriteData() 2681 when the processing was suspended */ 2682 pInBuffer_tmp = hhash->pHashInBuffPtr; /* pInBuffer_tmp is set to the input data address */ 2683 Size_tmp = hhash->HashInCount; /* Size_tmp contains the input data size in bytes */ 2684 2685 } 2686 else 2687 { 2688 /* Change the HASH state */ 2689 hhash->State = HAL_HASH_STATE_BUSY; 2690 2691 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as 2692 input parameters of HASH_WriteData() */ 2693 pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */ 2694 Size_tmp = Size; /* Size_tmp contains the input data size in bytes */ 2695 2696 /* Check if initialization phase has already be performed */ 2697 if (hhash->Phase == HAL_HASH_PHASE_READY) 2698 { 2699 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 2700 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 2701 } 2702 2703 /* Set the phase */ 2704 hhash->Phase = HAL_HASH_PHASE_PROCESS; 2705 2706 } 2707 2708 /* Write input buffer in Data register */ 2709 hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp); 2710 if (hhash->Status != HAL_OK) 2711 { 2712 return hhash->Status; 2713 } 2714 2715 /* If the process has not been suspended, move the state to Ready */ 2716 if (hhash->State != HAL_HASH_STATE_SUSPENDED) 2717 { 2718 /* Change the HASH state */ 2719 hhash->State = HAL_HASH_STATE_READY; 2720 } 2721 2722 /* Process Unlocked */ 2723 __HAL_UNLOCK(hhash); 2724 2725 /* Return function status */ 2726 return HAL_OK; 2727 2728 } 2729 else 2730 { 2731 return HAL_BUSY; 2732 } 2733 2734 2735 } 2736 2737 2738 /** 2739 * @brief If not already done, initialize the HASH peripheral then 2740 * processes pInBuffer in interruption mode. 2741 * @note Field hhash->Phase of HASH handle is tested to check whether or not 2742 * the Peripheral has already been initialized. 2743 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 2744 * HASH digest computation is corrupted. 2745 * @param hhash HASH handle. 2746 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 2747 * @param Size length of the input buffer in bytes, must be a multiple of 4. 2748 * @param Algorithm HASH algorithm. 2749 * @retval HAL status 2750 */ 2751 HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) 2752 { 2753 HAL_HASH_StateTypeDef State_tmp = hhash->State; 2754 __IO uint32_t inputaddr = (uint32_t) pInBuffer; 2755 uint32_t SizeVar = Size; 2756 2757 /* Make sure the input buffer size (in bytes) is a multiple of 4 */ 2758 if ((Size % 4U) != 0U) 2759 { 2760 return HAL_ERROR; 2761 } 2762 2763 /* Initiate HASH processing in case of start or resumption */ 2764 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 2765 { 2766 /* Check input parameters */ 2767 if ((pInBuffer == NULL) || (Size == 0U)) 2768 { 2769 hhash->State = HAL_HASH_STATE_READY; 2770 return HAL_ERROR; 2771 } 2772 2773 /* Process Locked */ 2774 __HAL_LOCK(hhash); 2775 2776 /* If resuming the HASH processing */ 2777 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 2778 { 2779 /* Change the HASH state */ 2780 hhash->State = HAL_HASH_STATE_BUSY; 2781 } 2782 else 2783 { 2784 /* Change the HASH state */ 2785 hhash->State = HAL_HASH_STATE_BUSY; 2786 2787 /* Check if initialization phase has already be performed */ 2788 if (hhash->Phase == HAL_HASH_PHASE_READY) 2789 { 2790 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 2791 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 2792 hhash->HashITCounter = 1; 2793 } 2794 else 2795 { 2796 hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */ 2797 } 2798 2799 /* Set the phase */ 2800 hhash->Phase = HAL_HASH_PHASE_PROCESS; 2801 2802 /* If DINIS is equal to 0 (for example if an incomplete block has been previously 2803 fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set. 2804 Therefore, first words are manually entered until DINIS raises, or until there 2805 is not more data to enter. */ 2806 while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U)) 2807 { 2808 2809 /* Write input data 4 bytes at a time */ 2810 HASH->DIN = *(uint32_t *)inputaddr; 2811 inputaddr += 4U; 2812 SizeVar -= 4U; 2813 } 2814 2815 /* If DINIS is still not set or if all the data have been fed, stop here */ 2816 if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U)) 2817 { 2818 /* Change the HASH state */ 2819 hhash->State = HAL_HASH_STATE_READY; 2820 2821 /* Process Unlock */ 2822 __HAL_UNLOCK(hhash); 2823 2824 /* Return function status */ 2825 return HAL_OK; 2826 } 2827 2828 /* otherwise, carry on in interrupt-mode */ 2829 hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data 2830 to be fed to the Peripheral */ 2831 hhash->pHashInBuffPtr = (uint8_t *)inputaddr; /* Points at data which will be fed to the Peripheral at 2832 the next interruption */ 2833 /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain 2834 the information describing where the HASH process is stopped. 2835 These variables are used later on to resume the HASH processing at the 2836 correct location. */ 2837 2838 } 2839 2840 /* Set multi buffers accumulation flag */ 2841 hhash->Accumulation = 1U; 2842 2843 /* Process Unlock */ 2844 __HAL_UNLOCK(hhash); 2845 2846 /* Enable Data Input interrupt */ 2847 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); 2848 2849 /* Return function status */ 2850 return HAL_OK; 2851 2852 } 2853 else 2854 { 2855 return HAL_BUSY; 2856 } 2857 2858 } 2859 2860 2861 2862 /** 2863 * @brief Initialize the HASH peripheral, next process pInBuffer then 2864 * read the computed digest in interruption mode. 2865 * @note Digest is available in pOutBuffer. 2866 * @param hhash HASH handle. 2867 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 2868 * @param Size length of the input buffer in bytes. 2869 * @param pOutBuffer pointer to the computed digest. 2870 * @param Algorithm HASH algorithm. 2871 * @retval HAL status 2872 */ 2873 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 2874 uint32_t Algorithm) 2875 { 2876 HAL_HASH_StateTypeDef State_tmp = hhash->State; 2877 __IO uint32_t inputaddr = (uint32_t) pInBuffer; 2878 uint32_t polling_step = 0U; 2879 uint32_t initialization_skipped = 0U; 2880 uint32_t SizeVar = Size; 2881 2882 /* If State is ready or suspended, start or resume IT-based HASH processing */ 2883 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 2884 { 2885 /* Check input parameters */ 2886 if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL)) 2887 { 2888 hhash->State = HAL_HASH_STATE_READY; 2889 return HAL_ERROR; 2890 } 2891 2892 /* Process Locked */ 2893 __HAL_LOCK(hhash); 2894 2895 /* Change the HASH state */ 2896 hhash->State = HAL_HASH_STATE_BUSY; 2897 2898 /* Initialize IT counter */ 2899 hhash->HashITCounter = 1; 2900 2901 /* Check if initialization phase has already be performed */ 2902 if (hhash->Phase == HAL_HASH_PHASE_READY) 2903 { 2904 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 2905 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 2906 2907 /* Configure the number of valid bits in last word of the message */ 2908 __HAL_HASH_SET_NBVALIDBITS(SizeVar); 2909 2910 2911 hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data 2912 to be fed to the Peripheral */ 2913 hhash->pHashInBuffPtr = pInBuffer; /* Points at data which will be fed to the Peripheral at 2914 the next interruption */ 2915 /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain 2916 the information describing where the HASH process is stopped. 2917 These variables are used later on to resume the HASH processing at the 2918 correct location. */ 2919 2920 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ 2921 } 2922 else 2923 { 2924 initialization_skipped = 1; /* info user later on in case of multi-buffer */ 2925 } 2926 2927 /* Set the phase */ 2928 hhash->Phase = HAL_HASH_PHASE_PROCESS; 2929 2930 /* If DINIS is equal to 0 (for example if an incomplete block has been previously 2931 fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set. 2932 Therefore, first words are manually entered until DINIS raises. */ 2933 while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U)) 2934 { 2935 polling_step = 1U; /* note that some words are entered before enabling the interrupt */ 2936 2937 /* Write input data 4 bytes at a time */ 2938 HASH->DIN = *(uint32_t *)inputaddr; 2939 inputaddr += 4U; 2940 SizeVar -= 4U; 2941 } 2942 2943 if (polling_step == 1U) 2944 { 2945 if (SizeVar == 0U) 2946 { 2947 /* If all the data have been entered at this point, it only remains to 2948 read the digest */ 2949 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ 2950 2951 /* Start the Digest calculation */ 2952 __HAL_HASH_START_DIGEST(); 2953 /* Process Unlock */ 2954 __HAL_UNLOCK(hhash); 2955 2956 /* Enable Interrupts */ 2957 __HAL_HASH_ENABLE_IT(HASH_IT_DCI); 2958 2959 /* Return function status */ 2960 return HAL_OK; 2961 } 2962 else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) 2963 { 2964 /* It remains data to enter and the Peripheral is ready to trigger DINIE, 2965 carry on as usual. 2966 Update HashInCount and pHashInBuffPtr accordingly. */ 2967 hhash->HashInCount = SizeVar; 2968 hhash->pHashInBuffPtr = (uint8_t *)inputaddr; 2969 /* Update the configuration of the number of valid bits in last word of the message */ 2970 __HAL_HASH_SET_NBVALIDBITS(SizeVar); 2971 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ 2972 if (initialization_skipped == 1U) 2973 { 2974 hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */ 2975 } 2976 } 2977 else 2978 { 2979 /* DINIS is not set but it remains a few data to enter (not enough for a full word). 2980 Manually enter the last bytes before enabling DCIE. */ 2981 __HAL_HASH_SET_NBVALIDBITS(SizeVar); 2982 HASH->DIN = *(uint32_t *)inputaddr; 2983 2984 /* Start the Digest calculation */ 2985 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ 2986 __HAL_HASH_START_DIGEST(); 2987 /* Process Unlock */ 2988 __HAL_UNLOCK(hhash); 2989 2990 /* Enable Interrupts */ 2991 __HAL_HASH_ENABLE_IT(HASH_IT_DCI); 2992 2993 /* Return function status */ 2994 return HAL_OK; 2995 } 2996 } /* if (polling_step == 1) */ 2997 2998 2999 /* Process Unlock */ 3000 __HAL_UNLOCK(hhash); 3001 3002 /* Enable Interrupts */ 3003 __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 3004 3005 /* Return function status */ 3006 return HAL_OK; 3007 } 3008 else 3009 { 3010 return HAL_BUSY; 3011 } 3012 3013 } 3014 3015 3016 /** 3017 * @brief Initialize the HASH peripheral then initiate a DMA transfer 3018 * to feed the input buffer to the Peripheral. 3019 * @note If MDMAT bit is set before calling this function (multi-buffer 3020 * HASH processing case), the input buffer size (in bytes) must be 3021 * a multiple of 4 otherwise, the HASH digest computation is corrupted. 3022 * For the processing of the last buffer of the thread, MDMAT bit must 3023 * be reset and the buffer length (in bytes) doesn't have to be a 3024 * multiple of 4. 3025 * @param hhash HASH handle. 3026 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 3027 * @param Size length of the input buffer in bytes. 3028 * @param Algorithm HASH algorithm. 3029 * @retval HAL status 3030 */ 3031 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) 3032 { 3033 uint32_t inputaddr; 3034 uint32_t inputSize; 3035 HAL_StatusTypeDef status ; 3036 HAL_HASH_StateTypeDef State_tmp = hhash->State; 3037 3038 3039 /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set 3040 (case of multi-buffer HASH processing) */ 3041 assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size)); 3042 3043 /* If State is ready or suspended, start or resume polling-based HASH processing */ 3044 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 3045 { 3046 /* Check input parameters */ 3047 if ((pInBuffer == NULL) || (Size == 0U) || 3048 /* Check phase coherency. Phase must be 3049 either READY (fresh start) 3050 or PROCESS (multi-buffer HASH management) */ 3051 ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash))))) 3052 { 3053 hhash->State = HAL_HASH_STATE_READY; 3054 return HAL_ERROR; 3055 } 3056 3057 3058 /* Process Locked */ 3059 __HAL_LOCK(hhash); 3060 3061 /* If not a resumption case */ 3062 if (hhash->State == HAL_HASH_STATE_READY) 3063 { 3064 /* Change the HASH state */ 3065 hhash->State = HAL_HASH_STATE_BUSY; 3066 3067 /* Check if initialization phase has already been performed. 3068 If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the 3069 API is processing a new input data message in case of multi-buffer HASH 3070 computation. */ 3071 if (hhash->Phase == HAL_HASH_PHASE_READY) 3072 { 3073 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 3074 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 3075 3076 /* Set the phase */ 3077 hhash->Phase = HAL_HASH_PHASE_PROCESS; 3078 } 3079 3080 /* Configure the Number of valid bits in last word of the message */ 3081 __HAL_HASH_SET_NBVALIDBITS(Size); 3082 3083 inputaddr = (uint32_t)pInBuffer; /* DMA transfer start address */ 3084 inputSize = Size; /* DMA transfer size (in bytes) */ 3085 3086 /* In case of suspension request, save the starting parameters */ 3087 hhash->pHashInBuffPtr = pInBuffer; /* DMA transfer start address */ 3088 hhash->HashInCount = Size; /* DMA transfer size (in bytes) */ 3089 3090 } 3091 /* If resumption case */ 3092 else 3093 { 3094 /* Change the HASH state */ 3095 hhash->State = HAL_HASH_STATE_BUSY; 3096 3097 /* Resumption case, inputaddr and inputSize are not set to the API input parameters 3098 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the 3099 processing was suspended */ 3100 inputaddr = (uint32_t)hhash->pHashInBuffPtr; /* DMA transfer start address */ 3101 inputSize = hhash->HashInCount; /* DMA transfer size (in bytes) */ 3102 3103 } 3104 3105 /* Set the HASH DMA transfer complete callback */ 3106 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; 3107 /* Set the DMA error callback */ 3108 hhash->hdmain->XferErrorCallback = HASH_DMAError; 3109 3110 /* Store number of words already pushed to manage proper DMA processing suspension */ 3111 hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED(); 3112 3113 /* Enable the DMA In DMA stream */ 3114 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \ 3115 (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \ 3116 (inputSize / 4U))); 3117 3118 /* Enable DMA requests */ 3119 SET_BIT(HASH->CR, HASH_CR_DMAE); 3120 3121 /* Process Unlock */ 3122 __HAL_UNLOCK(hhash); 3123 3124 /* Return function status */ 3125 if (status != HAL_OK) 3126 { 3127 /* Update HASH state machine to error */ 3128 hhash->State = HAL_HASH_STATE_ERROR; 3129 } 3130 3131 return status; 3132 } 3133 else 3134 { 3135 return HAL_BUSY; 3136 } 3137 } 3138 3139 /** 3140 * @brief Return the computed digest. 3141 * @note The API waits for DCIS to be set then reads the computed digest. 3142 * @param hhash HASH handle. 3143 * @param pOutBuffer pointer to the computed digest. 3144 * @param Timeout Timeout value. 3145 * @retval HAL status 3146 */ 3147 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) 3148 { 3149 3150 if (hhash->State == HAL_HASH_STATE_READY) 3151 { 3152 /* Check parameter */ 3153 if (pOutBuffer == NULL) 3154 { 3155 return HAL_ERROR; 3156 } 3157 3158 /* Process Locked */ 3159 __HAL_LOCK(hhash); 3160 3161 /* Change the HASH state to busy */ 3162 hhash->State = HAL_HASH_STATE_BUSY; 3163 3164 /* Wait for DCIS flag to be set */ 3165 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) 3166 { 3167 return HAL_TIMEOUT; 3168 } 3169 3170 /* Read the message digest */ 3171 HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH()); 3172 3173 /* Change the HASH state to ready */ 3174 hhash->State = HAL_HASH_STATE_READY; 3175 3176 /* Reset HASH state machine */ 3177 hhash->Phase = HAL_HASH_PHASE_READY; 3178 3179 /* Process UnLock */ 3180 __HAL_UNLOCK(hhash); 3181 3182 /* Return function status */ 3183 return HAL_OK; 3184 3185 } 3186 else 3187 { 3188 return HAL_BUSY; 3189 } 3190 3191 } 3192 3193 3194 /** 3195 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then 3196 * read the computed digest. 3197 * @note Digest is available in pOutBuffer. 3198 * @note Same key is used for the inner and the outer hash functions; pointer to key and 3199 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 3200 * @param hhash HASH handle. 3201 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 3202 * @param Size length of the input buffer in bytes. 3203 * @param pOutBuffer pointer to the computed digest. 3204 * @param Timeout Timeout value. 3205 * @param Algorithm HASH algorithm. 3206 * @retval HAL status 3207 */ 3208 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 3209 uint32_t Timeout, uint32_t Algorithm) 3210 { 3211 HAL_HASH_StateTypeDef State_tmp = hhash->State; 3212 3213 /* If State is ready or suspended, start or resume polling-based HASH processing */ 3214 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 3215 { 3216 /* Check input parameters */ 3217 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) 3218 || (pOutBuffer == NULL)) 3219 { 3220 hhash->State = HAL_HASH_STATE_READY; 3221 return HAL_ERROR; 3222 } 3223 3224 /* Process Locked */ 3225 __HAL_LOCK(hhash); 3226 3227 /* Change the HASH state */ 3228 hhash->State = HAL_HASH_STATE_BUSY; 3229 3230 /* Check if initialization phase has already be performed */ 3231 if (hhash->Phase == HAL_HASH_PHASE_READY) 3232 { 3233 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */ 3234 if (hhash->Init.KeySize > 64U) 3235 { 3236 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 3237 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); 3238 } 3239 else 3240 { 3241 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 3242 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); 3243 } 3244 /* Set the phase to Step 1 */ 3245 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; 3246 /* Resort to hhash internal fields to feed the Peripheral. 3247 Parameters will be updated in case of suspension to contain the proper 3248 information at resumption time. */ 3249 hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */ 3250 hhash->pHashInBuffPtr = pInBuffer; /* Input data address, HMAC_Processing input 3251 parameter for Step 2 */ 3252 hhash->HashInCount = Size; /* Input data size, HMAC_Processing input 3253 parameter for Step 2 */ 3254 hhash->HashBuffSize = Size; /* Store the input buffer size for the whole HMAC process*/ 3255 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address, HMAC_Processing input parameter for Step 3256 1 and Step 3 */ 3257 hhash->HashKeyCount = hhash->Init.KeySize; /* Key size, HMAC_Processing input parameter for Step 1 3258 and Step 3 */ 3259 } 3260 3261 /* Carry out HMAC processing */ 3262 return HMAC_Processing(hhash, Timeout); 3263 3264 } 3265 else 3266 { 3267 return HAL_BUSY; 3268 } 3269 } 3270 3271 3272 3273 /** 3274 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then 3275 * read the computed digest in interruption mode. 3276 * @note Digest is available in pOutBuffer. 3277 * @note Same key is used for the inner and the outer hash functions; pointer to key and 3278 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 3279 * @param hhash HASH handle. 3280 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 3281 * @param Size length of the input buffer in bytes. 3282 * @param pOutBuffer pointer to the computed digest. 3283 * @param Algorithm HASH algorithm. 3284 * @retval HAL status 3285 */ 3286 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 3287 uint32_t Algorithm) 3288 { 3289 HAL_HASH_StateTypeDef State_tmp = hhash->State; 3290 3291 /* If State is ready or suspended, start or resume IT-based HASH processing */ 3292 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 3293 { 3294 /* Check input parameters */ 3295 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) 3296 || (pOutBuffer == NULL)) 3297 { 3298 hhash->State = HAL_HASH_STATE_READY; 3299 return HAL_ERROR; 3300 } 3301 3302 /* Process Locked */ 3303 __HAL_LOCK(hhash); 3304 3305 /* Change the HASH state */ 3306 hhash->State = HAL_HASH_STATE_BUSY; 3307 3308 /* Initialize IT counter */ 3309 hhash->HashITCounter = 1; 3310 3311 /* Check if initialization phase has already be performed */ 3312 if (hhash->Phase == HAL_HASH_PHASE_READY) 3313 { 3314 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */ 3315 if (hhash->Init.KeySize > 64U) 3316 { 3317 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 3318 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); 3319 } 3320 else 3321 { 3322 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 3323 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); 3324 } 3325 3326 /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount 3327 to feed the Peripheral whatever the HMAC step. 3328 Lines below are set to start HMAC Step 1 processing where key is entered first. */ 3329 hhash->HashInCount = hhash->Init.KeySize; /* Key size */ 3330 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* Key address */ 3331 3332 /* Store input and output parameters in handle fields to manage steps transition 3333 or possible HMAC suspension/resumption */ 3334 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */ 3335 hhash->pHashMsgBuffPtr = pInBuffer; /* Input message address */ 3336 hhash->HashBuffSize = Size; /* Input message size (in bytes) */ 3337 hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */ 3338 3339 /* Configure the number of valid bits in last word of the key */ 3340 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); 3341 3342 /* Set the phase to Step 1 */ 3343 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; 3344 } 3345 else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)) 3346 { 3347 /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */ 3348 3349 } 3350 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) 3351 { 3352 /* Restart IT-based HASH processing after Step 2 suspension */ 3353 3354 } 3355 else 3356 { 3357 /* Error report as phase incorrect */ 3358 /* Process Unlock */ 3359 __HAL_UNLOCK(hhash); 3360 hhash->State = HAL_HASH_STATE_READY; 3361 return HAL_ERROR; 3362 } 3363 3364 /* Process Unlock */ 3365 __HAL_UNLOCK(hhash); 3366 3367 /* Enable Interrupts */ 3368 __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 3369 3370 /* Return function status */ 3371 return HAL_OK; 3372 } 3373 else 3374 { 3375 return HAL_BUSY; 3376 } 3377 3378 } 3379 3380 3381 3382 /** 3383 * @brief Initialize the HASH peripheral in HMAC mode then initiate the required 3384 * DMA transfers to feed the key and the input buffer to the Peripheral. 3385 * @note Same key is used for the inner and the outer hash functions; pointer to key and 3386 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 3387 * @note In case of multi-buffer HMAC processing, the input buffer size (in bytes) must 3388 * be a multiple of 4 otherwise, the HASH digest computation is corrupted. 3389 * Only the length of the last buffer of the thread doesn't have to be a 3390 * multiple of 4. 3391 * @param hhash HASH handle. 3392 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 3393 * @param Size length of the input buffer in bytes. 3394 * @param Algorithm HASH algorithm. 3395 * @retval HAL status 3396 */ 3397 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) 3398 { 3399 uint32_t inputaddr; 3400 uint32_t inputSize; 3401 HAL_StatusTypeDef status ; 3402 HAL_HASH_StateTypeDef State_tmp = hhash->State; 3403 /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation 3404 is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */ 3405 assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size)); 3406 /* If State is ready or suspended, start or resume DMA-based HASH processing */ 3407 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 3408 { 3409 /* Check input parameters */ 3410 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || 3411 /* Check phase coherency. Phase must be 3412 either READY (fresh start) 3413 or one of HMAC PROCESS steps (multi-buffer HASH management) */ 3414 ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash))))) 3415 { 3416 hhash->State = HAL_HASH_STATE_READY; 3417 return HAL_ERROR; 3418 } 3419 3420 3421 /* Process Locked */ 3422 __HAL_LOCK(hhash); 3423 3424 /* If not a case of resumption after suspension */ 3425 if (hhash->State == HAL_HASH_STATE_READY) 3426 { 3427 /* Check whether or not initialization phase has already be performed */ 3428 if (hhash->Phase == HAL_HASH_PHASE_READY) 3429 { 3430 /* Change the HASH state */ 3431 hhash->State = HAL_HASH_STATE_BUSY; 3432 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits. 3433 At the same time, ensure MDMAT bit is cleared. */ 3434 if (hhash->Init.KeySize > 64U) 3435 { 3436 MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 3437 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); 3438 } 3439 else 3440 { 3441 MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 3442 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); 3443 } 3444 /* Store input aparameters in handle fields to manage steps transition 3445 or possible HMAC suspension/resumption */ 3446 hhash->HashInCount = hhash->Init.KeySize; /* Initial size for first DMA transfer (key size) */ 3447 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */ 3448 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */ 3449 hhash->pHashMsgBuffPtr = pInBuffer; /* Input data address */ 3450 hhash->HashBuffSize = Size; /* input data size (in bytes) */ 3451 3452 /* Set DMA input parameters */ 3453 inputaddr = (uint32_t)(hhash->Init.pKey); /* Address passed to DMA (start by entering Key message) */ 3454 inputSize = hhash->Init.KeySize; /* Size for first DMA transfer (in bytes) */ 3455 3456 /* Configure the number of valid bits in last word of the key */ 3457 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); 3458 3459 /* Set the phase to Step 1 */ 3460 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; 3461 3462 } 3463 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) 3464 { 3465 /* Process a new input data message in case of multi-buffer HMAC processing 3466 (this is not a resumption case) */ 3467 3468 /* Change the HASH state */ 3469 hhash->State = HAL_HASH_STATE_BUSY; 3470 3471 /* Save input parameters to be able to manage possible suspension/resumption */ 3472 hhash->HashInCount = Size; /* Input message address */ 3473 hhash->pHashInBuffPtr = pInBuffer; /* Input message size in bytes */ 3474 3475 /* Set DMA input parameters */ 3476 inputaddr = (uint32_t)pInBuffer; /* Input message address */ 3477 inputSize = Size; /* Input message size in bytes */ 3478 3479 if (hhash->DigestCalculationDisable == RESET) 3480 { 3481 /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */ 3482 __HAL_HASH_RESET_MDMAT(); 3483 __HAL_HASH_SET_NBVALIDBITS(inputSize); 3484 } 3485 } 3486 else 3487 { 3488 /* Phase not aligned with handle READY state */ 3489 __HAL_UNLOCK(hhash); 3490 /* Return function status */ 3491 return HAL_ERROR; 3492 } 3493 } 3494 else 3495 { 3496 /* Resumption case (phase may be Step 1, 2 or 3) */ 3497 3498 /* Change the HASH state */ 3499 hhash->State = HAL_HASH_STATE_BUSY; 3500 3501 /* Set DMA input parameters at resumption location; 3502 inputaddr and inputSize are not set to the API input parameters 3503 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the 3504 processing was suspended. */ 3505 inputaddr = (uint32_t)(hhash->pHashInBuffPtr); /* Input message address */ 3506 inputSize = hhash->HashInCount; /* Input message size in bytes */ 3507 } 3508 3509 3510 /* Set the HASH DMA transfer complete callback */ 3511 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; 3512 /* Set the DMA error callback */ 3513 hhash->hdmain->XferErrorCallback = HASH_DMAError; 3514 3515 /* Store number of words already pushed to manage proper DMA processing suspension */ 3516 hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED(); 3517 3518 /* Enable the DMA In DMA stream */ 3519 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \ 3520 (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \ 3521 : (inputSize / 4U))); 3522 3523 /* Enable DMA requests */ 3524 SET_BIT(HASH->CR, HASH_CR_DMAE); 3525 3526 /* Process Unlocked */ 3527 __HAL_UNLOCK(hhash); 3528 3529 /* Return function status */ 3530 if (status != HAL_OK) 3531 { 3532 /* Update HASH state machine to error */ 3533 hhash->State = HAL_HASH_STATE_ERROR; 3534 } 3535 3536 /* Return function status */ 3537 return status; 3538 } 3539 else 3540 { 3541 return HAL_BUSY; 3542 } 3543 } 3544 /** 3545 * @} 3546 */ 3547 3548 #endif /* HAL_HASH_MODULE_ENABLED */ 3549 3550 /** 3551 * @} 3552 */ 3553 #endif /* HASH*/ 3554 /** 3555 * @} 3556 */ 3557
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |