STM32H735xx HAL User Manual
|
00001 /** 00002 ****************************************************************************** 00003 * @file stm32h7xx_hal_hash.c 00004 * @author MCD Application Team 00005 * @brief HASH HAL module driver. 00006 * This file provides firmware functions to manage the following 00007 * functionalities of the HASH peripheral: 00008 * + Initialization and de-initialization methods 00009 * + HASH or HMAC processing in polling mode 00010 * + HASH or HMAC processing in interrupt mode 00011 * + HASH or HMAC processing in DMA mode 00012 * + Peripheral State methods 00013 * + HASH or HMAC processing suspension/resumption 00014 * 00015 ****************************************************************************** 00016 * @attention 00017 * 00018 * Copyright (c) 2017 STMicroelectronics. 00019 * All rights reserved. 00020 * 00021 * This software is licensed under terms that can be found in the LICENSE file 00022 * in the root directory of this software component. 00023 * If no LICENSE file comes with this software, it is provided AS-IS. 00024 * 00025 ****************************************************************************** 00026 @verbatim 00027 =============================================================================== 00028 ##### How to use this driver ##### 00029 =============================================================================== 00030 [..] 00031 The HASH HAL driver can be used as follows: 00032 00033 (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit(): 00034 (##) Enable the HASH interface clock using __HASH_CLK_ENABLE() 00035 (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT()) 00036 (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority() 00037 (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ() 00038 (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API 00039 (##) When resorting to DMA-based APIs (e.g. HAL_HASH_xxx_Start_DMA()) 00040 (+++) Enable the DMAx interface clock using 00041 __DMAx_CLK_ENABLE() 00042 (+++) Configure and enable one DMA stream to manage data transfer from 00043 memory to peripheral (input stream). Managing data transfer from 00044 peripheral to memory can be performed only using CPU. 00045 (+++) Associate the initialized DMA handle to the HASH DMA handle 00046 using __HAL_LINKDMA() 00047 (+++) Configure the priority and enable the NVIC for the transfer complete 00048 interrupt on the DMA stream: use 00049 HAL_NVIC_SetPriority() and 00050 HAL_NVIC_EnableIRQ() 00051 00052 (#)Initialize the HASH HAL using HAL_HASH_Init(). This function: 00053 (##) resorts to HAL_HASH_MspInit() for low-level initialization, 00054 (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit. 00055 00056 (#)Three processing schemes are available: 00057 (##) Polling mode: processing APIs are blocking functions 00058 i.e. they process the data and wait till the digest computation is finished, 00059 e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC 00060 (##) Interrupt mode: processing APIs are not blocking functions 00061 i.e. they process the data under interrupt, 00062 e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC 00063 (##) DMA mode: processing APIs are not blocking functions and the CPU is 00064 not used for data transfer i.e. the data transfer is ensured by DMA, 00065 e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA() 00066 for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish() 00067 is then required to retrieve the digest. 00068 00069 (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is 00070 initialized and processes the buffer fed in input. When the input data have all been 00071 fed to the Peripheral, the digest computation can start. 00072 00073 (#)Multi-buffer processing is possible in polling, interrupt and DMA modes. 00074 (##) In polling mode, only multi-buffer HASH processing is possible. 00075 API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one. 00076 User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as 00077 well the computed digest. 00078 00079 (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer, 00080 except for the last one. 00081 User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as 00082 well the computed digest. 00083 00084 (##) In DMA mode, multi-buffer HASH and HMAC processing are possible. 00085 (+++) HASH processing: once initialization is done, MDMAT bit must be set 00086 through __HAL_HASH_SET_MDMAT() macro. 00087 From that point, each buffer can be fed to the Peripheral through HAL_HASH_xxx_Start_DMA() API. 00088 Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT() 00089 macro then wrap-up the HASH processing in feeding the last input buffer through the 00090 same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to 00091 API HAL_HASH_xxx_Finish(). 00092 (+++) HMAC processing (requires to resort to extended functions): 00093 after initialization, the key and the first input buffer are entered 00094 in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and 00095 starts step 2. 00096 The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this 00097 point, the HMAC processing is still carrying out step 2. 00098 Then, step 2 for the last input buffer and step 3 are carried out by a single call 00099 to HAL_HMACEx_xxx_Step2_3_DMA(). 00100 00101 The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish(). 00102 00103 00104 (#)Context swapping. 00105 (##) Two APIs are available to suspend HASH or HMAC processing: 00106 (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode), 00107 (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA. 00108 00109 (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows 00110 to save in memory the Peripheral context. This context can be restored afterwards 00111 to resume the HASH processing thanks to HAL_HASH_ContextRestoring(). 00112 00113 (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension 00114 time, processing can be restarted with the same API call (same API, same handle, 00115 same parameters) as done before the suspension. Relevant parameters to restart at 00116 the proper location are internally saved in the HASH handle. 00117 00118 (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral. 00119 00120 *** Remarks on message length *** 00121 =================================== 00122 [..] 00123 (#) HAL in interruption mode (interruptions driven) 00124 00125 (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes. 00126 This is why, for driver implementation simplicity’s sake, user is requested to enter a message the 00127 length of which is a multiple of 4 bytes. 00128 00129 (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR 00130 to specify which bits to discard at the end of the complete message to process only the message bits 00131 and not extra bits. 00132 00133 (##) If user needs to perform a hash computation of a large input buffer that is spread around various places 00134 in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it becomes 00135 necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral. 00136 It is advised to the user to 00137 (+++) achieve the first formatting operation by software then enter the data 00138 (+++) while the Peripheral is processing the first input set, carry out the second formatting 00139 operation by software, to be ready when DINIS occurs. 00140 (+++) repeat step 2 until the whole message is processed. 00141 00142 [..] 00143 (#) HAL in DMA mode 00144 00145 (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis. 00146 The same field described above in HASH_STR is used to specify which bits to discard at the end of the 00147 DMA transfer to process only the message bits and not extra bits. Due to hardware implementation, 00148 this is possible only at the end of the complete message. When several DMA transfers are needed to 00149 enter the message, this is not applicable at the end of the intermediary transfers. 00150 00151 (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive 00152 chunks of data by software while the DMA transfer and processing is on-going for the first parts of 00153 the message. Due to the 32-bit alignment required for the DMA transfer, it is underlined that the 00154 software formatting operation is more complex than in the IT mode. 00155 00156 *** Callback registration *** 00157 =================================== 00158 [..] 00159 (#) The compilation define USE_HAL_HASH_REGISTER_CALLBACKS when set to 1 00160 allows the user to configure dynamically the driver callbacks. 00161 Use function HAL_HASH_RegisterCallback() to register a user callback. 00162 00163 (#) Function HAL_HASH_RegisterCallback() allows to register following callbacks: 00164 (+) InCpltCallback : callback for input completion. 00165 (+) DgstCpltCallback : callback for digest computation completion. 00166 (+) ErrorCallback : callback for error. 00167 (+) MspInitCallback : HASH MspInit. 00168 (+) MspDeInitCallback : HASH MspDeInit. 00169 This function takes as parameters the HAL peripheral handle, the Callback ID 00170 and a pointer to the user callback function. 00171 00172 (#) Use function HAL_HASH_UnRegisterCallback() to reset a callback to the default 00173 weak (surcharged) function. 00174 HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle, 00175 and the Callback ID. 00176 This function allows to reset following callbacks: 00177 (+) InCpltCallback : callback for input completion. 00178 (+) DgstCpltCallback : callback for digest computation completion. 00179 (+) ErrorCallback : callback for error. 00180 (+) MspInitCallback : HASH MspInit. 00181 (+) MspDeInitCallback : HASH MspDeInit. 00182 00183 (#) By default, after the HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET 00184 all callbacks are reset to the corresponding legacy weak (surcharged) functions: 00185 examples HAL_HASH_InCpltCallback(), HAL_HASH_DgstCpltCallback() 00186 Exception done for MspInit and MspDeInit callbacks that are respectively 00187 reset to the legacy weak (surcharged) functions in the HAL_HASH_Init 00188 and HAL_HASH_DeInit only when these callbacks are null (not registered beforehand) 00189 If not, MspInit or MspDeInit are not null, the HAL_HASH_Init and HAL_HASH_DeInit 00190 keep and use the user MspInit/MspDeInit callbacks (registered beforehand). 00191 00192 Callbacks can be registered/unregistered in READY state only. 00193 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered 00194 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used 00195 during the Init/DeInit. 00196 In that case first register the MspInit/MspDeInit user callbacks 00197 using HAL_HASH_RegisterCallback before calling HAL_HASH_DeInit 00198 or HAL_HASH_Init function. 00199 00200 When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or 00201 not defined, the callback registering feature is not available 00202 and weak (surcharged) callbacks are used. 00203 00204 @endverbatim 00205 ****************************************************************************** 00206 */ 00207 00208 /* Includes ------------------------------------------------------------------*/ 00209 #include "stm32h7xx_hal.h" 00210 00211 00212 /** @addtogroup STM32H7xx_HAL_Driver 00213 * @{ 00214 */ 00215 #if defined (HASH) 00216 00217 /** @defgroup HASH HASH 00218 * @brief HASH HAL module driver. 00219 * @{ 00220 */ 00221 00222 #ifdef HAL_HASH_MODULE_ENABLED 00223 00224 /* Private typedef -----------------------------------------------------------*/ 00225 /* Private define ------------------------------------------------------------*/ 00226 /** @defgroup HASH_Private_Constants HASH Private Constants 00227 * @{ 00228 */ 00229 00230 /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status 00231 * @{ 00232 */ 00233 #define HASH_DIGEST_CALCULATION_NOT_STARTED ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */ 00234 #define HASH_DIGEST_CALCULATION_STARTED ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register */ 00235 /** 00236 * @} 00237 */ 00238 00239 /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers 00240 * @{ 00241 */ 00242 #define HASH_NUMBER_OF_CSR_REGISTERS 54U /*!< Number of Context Swap Registers */ 00243 /** 00244 * @} 00245 */ 00246 00247 /** @defgroup HASH_TimeOut_Value HASH TimeOut Value 00248 * @{ 00249 */ 00250 #define HASH_TIMEOUTVALUE 1000U /*!< Time-out value */ 00251 /** 00252 * @} 00253 */ 00254 00255 /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit 00256 * @{ 00257 */ 00258 #define HASH_DMA_SUSPENSION_WORDS_LIMIT 20U /*!< Number of words below which DMA suspension is aborted */ 00259 /** 00260 * @} 00261 */ 00262 00263 /** 00264 * @} 00265 */ 00266 00267 /* Private macro -------------------------------------------------------------*/ 00268 /* Private variables ---------------------------------------------------------*/ 00269 /* Private function prototypes -----------------------------------------------*/ 00270 /** @defgroup HASH_Private_Functions HASH Private Functions 00271 * @{ 00272 */ 00273 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma); 00274 static void HASH_DMAError(DMA_HandleTypeDef *hdma); 00275 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size); 00276 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, 00277 uint32_t Timeout); 00278 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); 00279 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash); 00280 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash); 00281 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout); 00282 /** 00283 * @} 00284 */ 00285 00286 /** @defgroup HASH_Exported_Functions HASH Exported Functions 00287 * @{ 00288 */ 00289 00290 /** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions 00291 * @brief Initialization, configuration and call-back functions. 00292 * 00293 @verbatim 00294 =============================================================================== 00295 ##### Initialization and de-initialization functions ##### 00296 =============================================================================== 00297 [..] This section provides functions allowing to: 00298 (+) Initialize the HASH according to the specified parameters 00299 in the HASH_InitTypeDef and create the associated handle 00300 (+) DeInitialize the HASH peripheral 00301 (+) Initialize the HASH MCU Specific Package (MSP) 00302 (+) DeInitialize the HASH MSP 00303 00304 [..] This section provides as well call back functions definitions for user 00305 code to manage: 00306 (+) Input data transfer to Peripheral completion 00307 (+) Calculated digest retrieval completion 00308 (+) Error management 00309 00310 00311 00312 @endverbatim 00313 * @{ 00314 */ 00315 00316 /** 00317 * @brief Initialize the HASH according to the specified parameters in the 00318 HASH_HandleTypeDef and create the associated handle. 00319 * @note Only MDMAT and DATATYPE bits of HASH Peripheral are set by HAL_HASH_Init(), 00320 * other configuration bits are set by HASH or HMAC processing APIs. 00321 * @note MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for 00322 * multi-buffer HASH processing, user needs to resort to 00323 * __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the 00324 * relevant APIs manage themselves the MDMAT bit. 00325 * @param hhash HASH handle 00326 * @retval HAL status 00327 */ 00328 HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash) 00329 { 00330 /* Check the hash handle allocation */ 00331 if (hhash == NULL) 00332 { 00333 return HAL_ERROR; 00334 } 00335 00336 /* Check the parameters */ 00337 assert_param(IS_HASH_DATATYPE(hhash->Init.DataType)); 00338 00339 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 00340 if (hhash->State == HAL_HASH_STATE_RESET) 00341 { 00342 /* Allocate lock resource and initialize it */ 00343 hhash->Lock = HAL_UNLOCKED; 00344 00345 /* Reset Callback pointers in HAL_HASH_STATE_RESET only */ 00346 hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */ 00347 hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation 00348 completion callback */ 00349 hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */ 00350 if (hhash->MspInitCallback == NULL) 00351 { 00352 hhash->MspInitCallback = HAL_HASH_MspInit; 00353 } 00354 00355 /* Init the low level hardware */ 00356 hhash->MspInitCallback(hhash); 00357 } 00358 #else 00359 if (hhash->State == HAL_HASH_STATE_RESET) 00360 { 00361 /* Allocate lock resource and initialize it */ 00362 hhash->Lock = HAL_UNLOCKED; 00363 00364 /* Init the low level hardware */ 00365 HAL_HASH_MspInit(hhash); 00366 } 00367 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ 00368 00369 /* Change the HASH state */ 00370 hhash->State = HAL_HASH_STATE_BUSY; 00371 00372 /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */ 00373 hhash->HashInCount = 0; 00374 hhash->HashBuffSize = 0; 00375 hhash->HashITCounter = 0; 00376 hhash->NbWordsAlreadyPushed = 0; 00377 /* Reset digest calculation bridle (MDMAT bit control) */ 00378 hhash->DigestCalculationDisable = RESET; 00379 /* Set phase to READY */ 00380 hhash->Phase = HAL_HASH_PHASE_READY; 00381 /* Reset suspension request flag */ 00382 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; 00383 00384 /* Set the data type bit */ 00385 MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType); 00386 /* Reset MDMAT bit */ 00387 __HAL_HASH_RESET_MDMAT(); 00388 /* Reset HASH handle status */ 00389 hhash->Status = HAL_OK; 00390 00391 /* Set the HASH state to Ready */ 00392 hhash->State = HAL_HASH_STATE_READY; 00393 00394 /* Initialise the error code */ 00395 hhash->ErrorCode = HAL_HASH_ERROR_NONE; 00396 00397 /* Return function status */ 00398 return HAL_OK; 00399 } 00400 00401 /** 00402 * @brief DeInitialize the HASH peripheral. 00403 * @param hhash HASH handle. 00404 * @retval HAL status 00405 */ 00406 HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash) 00407 { 00408 /* Check the HASH handle allocation */ 00409 if (hhash == NULL) 00410 { 00411 return HAL_ERROR; 00412 } 00413 00414 /* Change the HASH state */ 00415 hhash->State = HAL_HASH_STATE_BUSY; 00416 00417 /* Set the default HASH phase */ 00418 hhash->Phase = HAL_HASH_PHASE_READY; 00419 00420 /* Reset HashInCount, HashITCounter and HashBuffSize */ 00421 hhash->HashInCount = 0; 00422 hhash->HashBuffSize = 0; 00423 hhash->HashITCounter = 0; 00424 /* Reset digest calculation bridle (MDMAT bit control) */ 00425 hhash->DigestCalculationDisable = RESET; 00426 00427 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 00428 if (hhash->MspDeInitCallback == NULL) 00429 { 00430 hhash->MspDeInitCallback = HAL_HASH_MspDeInit; 00431 } 00432 00433 /* DeInit the low level hardware */ 00434 hhash->MspDeInitCallback(hhash); 00435 #else 00436 /* DeInit the low level hardware: CLOCK, NVIC */ 00437 HAL_HASH_MspDeInit(hhash); 00438 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ 00439 00440 00441 /* Reset HASH handle status */ 00442 hhash->Status = HAL_OK; 00443 00444 /* Set the HASH state to Ready */ 00445 hhash->State = HAL_HASH_STATE_RESET; 00446 00447 /* Initialise the error code */ 00448 hhash->ErrorCode = HAL_HASH_ERROR_NONE; 00449 00450 /* Reset multi buffers accumulation flag */ 00451 hhash->Accumulation = 0U; 00452 00453 /* Return function status */ 00454 return HAL_OK; 00455 } 00456 00457 /** 00458 * @brief Initialize the HASH MSP. 00459 * @param hhash HASH handle. 00460 * @retval None 00461 */ 00462 __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash) 00463 { 00464 /* Prevent unused argument(s) compilation warning */ 00465 UNUSED(hhash); 00466 00467 /* NOTE : This function should not be modified; when the callback is needed, 00468 HAL_HASH_MspInit() can be implemented in the user file. 00469 */ 00470 } 00471 00472 /** 00473 * @brief DeInitialize the HASH MSP. 00474 * @param hhash HASH handle. 00475 * @retval None 00476 */ 00477 __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash) 00478 { 00479 /* Prevent unused argument(s) compilation warning */ 00480 UNUSED(hhash); 00481 00482 /* NOTE : This function should not be modified; when the callback is needed, 00483 HAL_HASH_MspDeInit() can be implemented in the user file. 00484 */ 00485 } 00486 00487 /** 00488 * @brief Input data transfer complete call back. 00489 * @note HAL_HASH_InCpltCallback() is called when the complete input message 00490 * has been fed to the Peripheral. This API is invoked only when input data are 00491 * entered under interruption or through DMA. 00492 * @note In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set), 00493 * HAL_HASH_InCpltCallback() is called at the end of each buffer feeding 00494 * to the Peripheral. 00495 * @param hhash HASH handle. 00496 * @retval None 00497 */ 00498 __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash) 00499 { 00500 /* Prevent unused argument(s) compilation warning */ 00501 UNUSED(hhash); 00502 00503 /* NOTE : This function should not be modified; when the callback is needed, 00504 HAL_HASH_InCpltCallback() can be implemented in the user file. 00505 */ 00506 } 00507 00508 /** 00509 * @brief Digest computation complete call back. 00510 * @note HAL_HASH_DgstCpltCallback() is used under interruption, is not 00511 * relevant with DMA. 00512 * @param hhash HASH handle. 00513 * @retval None 00514 */ 00515 __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash) 00516 { 00517 /* Prevent unused argument(s) compilation warning */ 00518 UNUSED(hhash); 00519 00520 /* NOTE : This function should not be modified; when the callback is needed, 00521 HAL_HASH_DgstCpltCallback() can be implemented in the user file. 00522 */ 00523 } 00524 00525 /** 00526 * @brief Error callback. 00527 * @note Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...) 00528 * to retrieve the error type. 00529 * @param hhash HASH handle. 00530 * @retval None 00531 */ 00532 __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash) 00533 { 00534 /* Prevent unused argument(s) compilation warning */ 00535 UNUSED(hhash); 00536 00537 /* NOTE : This function should not be modified; when the callback is needed, 00538 HAL_HASH_ErrorCallback() can be implemented in the user file. 00539 */ 00540 } 00541 00542 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 00543 /** 00544 * @brief Register a User HASH Callback 00545 * To be used instead of the weak (surcharged) predefined callback 00546 * @param hhash HASH handle 00547 * @param CallbackID ID of the callback to be registered 00548 * This parameter can be one of the following values: 00549 * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID 00550 * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID 00551 * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID 00552 * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID 00553 * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID 00554 * @param pCallback pointer to the Callback function 00555 * @retval status 00556 */ 00557 HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID, 00558 pHASH_CallbackTypeDef pCallback) 00559 { 00560 HAL_StatusTypeDef status = HAL_OK; 00561 00562 if (pCallback == NULL) 00563 { 00564 /* Update the error code */ 00565 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 00566 return HAL_ERROR; 00567 } 00568 /* Process locked */ 00569 __HAL_LOCK(hhash); 00570 00571 if (HAL_HASH_STATE_READY == hhash->State) 00572 { 00573 switch (CallbackID) 00574 { 00575 case HAL_HASH_INPUTCPLT_CB_ID : 00576 hhash->InCpltCallback = pCallback; 00577 break; 00578 00579 case HAL_HASH_DGSTCPLT_CB_ID : 00580 hhash->DgstCpltCallback = pCallback; 00581 break; 00582 00583 case HAL_HASH_ERROR_CB_ID : 00584 hhash->ErrorCallback = pCallback; 00585 break; 00586 00587 case HAL_HASH_MSPINIT_CB_ID : 00588 hhash->MspInitCallback = pCallback; 00589 break; 00590 00591 case HAL_HASH_MSPDEINIT_CB_ID : 00592 hhash->MspDeInitCallback = pCallback; 00593 break; 00594 00595 default : 00596 /* Update the error code */ 00597 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 00598 /* update return status */ 00599 status = HAL_ERROR; 00600 break; 00601 } 00602 } 00603 else if (HAL_HASH_STATE_RESET == hhash->State) 00604 { 00605 switch (CallbackID) 00606 { 00607 case HAL_HASH_MSPINIT_CB_ID : 00608 hhash->MspInitCallback = pCallback; 00609 break; 00610 00611 case HAL_HASH_MSPDEINIT_CB_ID : 00612 hhash->MspDeInitCallback = pCallback; 00613 break; 00614 00615 default : 00616 /* Update the error code */ 00617 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 00618 /* update return status */ 00619 status = HAL_ERROR; 00620 break; 00621 } 00622 } 00623 else 00624 { 00625 /* Update the error code */ 00626 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 00627 /* update return status */ 00628 status = HAL_ERROR; 00629 } 00630 00631 /* Release Lock */ 00632 __HAL_UNLOCK(hhash); 00633 return status; 00634 } 00635 00636 /** 00637 * @brief Unregister a HASH Callback 00638 * HASH Callback is redirected to the weak (surcharged) predefined callback 00639 * @param hhash HASH handle 00640 * @param CallbackID ID of the callback to be unregistered 00641 * This parameter can be one of the following values: 00642 * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID 00643 * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID 00644 * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID 00645 * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID 00646 * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID 00647 * @retval status 00648 */ 00649 HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID) 00650 { 00651 HAL_StatusTypeDef status = HAL_OK; 00652 00653 /* Process locked */ 00654 __HAL_LOCK(hhash); 00655 00656 if (HAL_HASH_STATE_READY == hhash->State) 00657 { 00658 switch (CallbackID) 00659 { 00660 case HAL_HASH_INPUTCPLT_CB_ID : 00661 hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */ 00662 break; 00663 00664 case HAL_HASH_DGSTCPLT_CB_ID : 00665 hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation 00666 completion callback */ 00667 break; 00668 00669 case HAL_HASH_ERROR_CB_ID : 00670 hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */ 00671 break; 00672 00673 case HAL_HASH_MSPINIT_CB_ID : 00674 hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */ 00675 break; 00676 00677 case HAL_HASH_MSPDEINIT_CB_ID : 00678 hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ 00679 break; 00680 00681 default : 00682 /* Update the error code */ 00683 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 00684 /* update return status */ 00685 status = HAL_ERROR; 00686 break; 00687 } 00688 } 00689 else if (HAL_HASH_STATE_RESET == hhash->State) 00690 { 00691 switch (CallbackID) 00692 { 00693 case HAL_HASH_MSPINIT_CB_ID : 00694 hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */ 00695 break; 00696 00697 case HAL_HASH_MSPDEINIT_CB_ID : 00698 hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ 00699 break; 00700 00701 default : 00702 /* Update the error code */ 00703 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 00704 /* update return status */ 00705 status = HAL_ERROR; 00706 break; 00707 } 00708 } 00709 else 00710 { 00711 /* Update the error code */ 00712 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; 00713 /* update return status */ 00714 status = HAL_ERROR; 00715 } 00716 00717 /* Release Lock */ 00718 __HAL_UNLOCK(hhash); 00719 return status; 00720 } 00721 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 00722 00723 /** 00724 * @} 00725 */ 00726 00727 /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode 00728 * @brief HASH processing functions using polling mode. 00729 * 00730 @verbatim 00731 =============================================================================== 00732 ##### Polling mode HASH processing functions ##### 00733 =============================================================================== 00734 [..] This section provides functions allowing to calculate in polling mode 00735 the hash value using one of the following algorithms: 00736 (+) MD5 00737 (++) HAL_HASH_MD5_Start() 00738 (++) HAL_HASH_MD5_Accmlt() 00739 (++) HAL_HASH_MD5_Accmlt_End() 00740 (+) SHA1 00741 (++) HAL_HASH_SHA1_Start() 00742 (++) HAL_HASH_SHA1_Accmlt() 00743 (++) HAL_HASH_SHA1_Accmlt_End() 00744 00745 [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start(). 00746 00747 [..] In case of multi-buffer HASH processing (a single digest is computed while 00748 several buffers are fed to the Peripheral), the user can resort to successive calls 00749 to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call 00750 to HAL_HASH_xxx_Accumulate_End(). 00751 00752 @endverbatim 00753 * @{ 00754 */ 00755 00756 /** 00757 * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then 00758 * read the computed digest. 00759 * @note Digest is available in pOutBuffer. 00760 * @param hhash HASH handle. 00761 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00762 * @param Size length of the input buffer in bytes. 00763 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 00764 * @param Timeout Timeout value 00765 * @retval HAL status 00766 */ 00767 HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 00768 uint32_t Timeout) 00769 { 00770 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); 00771 } 00772 00773 /** 00774 * @brief If not already done, initialize the HASH peripheral in MD5 mode then 00775 * processes pInBuffer. 00776 * @note Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed 00777 * several input buffers back-to-back to the Peripheral that will yield a single 00778 * HASH signature once all buffers have been entered. Wrap-up of input 00779 * buffers feeding and retrieval of digest is done by a call to 00780 * HAL_HASH_MD5_Accmlt_End(). 00781 * @note Field hhash->Phase of HASH handle is tested to check whether or not 00782 * the Peripheral has already been initialized. 00783 * @note Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End() 00784 * to read it, feeding at the same time the last input buffer to the Peripheral. 00785 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 00786 * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able 00787 * to manage the ending buffer with a length in bytes not a multiple of 4. 00788 * @param hhash HASH handle. 00789 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00790 * @param Size length of the input buffer in bytes, must be a multiple of 4. 00791 * @retval HAL status 00792 */ 00793 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 00794 { 00795 return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); 00796 } 00797 00798 /** 00799 * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API. 00800 * @note Digest is available in pOutBuffer. 00801 * @param hhash HASH handle. 00802 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00803 * @param Size length of the input buffer in bytes. 00804 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 00805 * @param Timeout Timeout value 00806 * @retval HAL status 00807 */ 00808 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 00809 uint8_t *pOutBuffer, uint32_t Timeout) 00810 { 00811 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); 00812 } 00813 00814 /** 00815 * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then 00816 * read the computed digest. 00817 * @note Digest is available in pOutBuffer. 00818 * @param hhash HASH handle. 00819 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00820 * @param Size length of the input buffer in bytes. 00821 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 00822 * @param Timeout Timeout value 00823 * @retval HAL status 00824 */ 00825 HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 00826 uint32_t Timeout) 00827 { 00828 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); 00829 } 00830 00831 /** 00832 * @brief If not already done, initialize the HASH peripheral in SHA1 mode then 00833 * processes pInBuffer. 00834 * @note Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed 00835 * several input buffers back-to-back to the Peripheral that will yield a single 00836 * HASH signature once all buffers have been entered. Wrap-up of input 00837 * buffers feeding and retrieval of digest is done by a call to 00838 * HAL_HASH_SHA1_Accmlt_End(). 00839 * @note Field hhash->Phase of HASH handle is tested to check whether or not 00840 * the Peripheral has already been initialized. 00841 * @note Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End() 00842 * to read it, feeding at the same time the last input buffer to the Peripheral. 00843 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 00844 * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able 00845 * to manage the ending buffer with a length in bytes not a multiple of 4. 00846 * @param hhash HASH handle. 00847 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00848 * @param Size length of the input buffer in bytes, must be a multiple of 4. 00849 * @retval HAL status 00850 */ 00851 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 00852 { 00853 return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); 00854 } 00855 00856 /** 00857 * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API. 00858 * @note Digest is available in pOutBuffer. 00859 * @param hhash HASH handle. 00860 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00861 * @param Size length of the input buffer in bytes. 00862 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 00863 * @param Timeout Timeout value 00864 * @retval HAL status 00865 */ 00866 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 00867 uint8_t *pOutBuffer, uint32_t Timeout) 00868 { 00869 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); 00870 } 00871 00872 /** 00873 * @} 00874 */ 00875 00876 /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode 00877 * @brief HASH processing functions using interrupt mode. 00878 * 00879 @verbatim 00880 =============================================================================== 00881 ##### Interruption mode HASH processing functions ##### 00882 =============================================================================== 00883 [..] This section provides functions allowing to calculate in interrupt mode 00884 the hash value using one of the following algorithms: 00885 (+) MD5 00886 (++) HAL_HASH_MD5_Start_IT() 00887 (++) HAL_HASH_MD5_Accmlt_IT() 00888 (++) HAL_HASH_MD5_Accmlt_End_IT() 00889 (+) SHA1 00890 (++) HAL_HASH_SHA1_Start_IT() 00891 (++) HAL_HASH_SHA1_Accmlt_IT() 00892 (++) HAL_HASH_SHA1_Accmlt_End_IT() 00893 00894 [..] API HAL_HASH_IRQHandler() manages each HASH interruption. 00895 00896 [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in 00897 HMAC processing mode. 00898 00899 00900 @endverbatim 00901 * @{ 00902 */ 00903 00904 /** 00905 * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then 00906 * read the computed digest in interruption mode. 00907 * @note Digest is available in pOutBuffer. 00908 * @param hhash HASH handle. 00909 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00910 * @param Size length of the input buffer in bytes. 00911 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 00912 * @retval HAL status 00913 */ 00914 HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 00915 uint8_t *pOutBuffer) 00916 { 00917 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5); 00918 } 00919 00920 /** 00921 * @brief If not already done, initialize the HASH peripheral in MD5 mode then 00922 * processes pInBuffer in interruption mode. 00923 * @note Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed 00924 * several input buffers back-to-back to the Peripheral that will yield a single 00925 * HASH signature once all buffers have been entered. Wrap-up of input 00926 * buffers feeding and retrieval of digest is done by a call to 00927 * HAL_HASH_MD5_Accmlt_End_IT(). 00928 * @note Field hhash->Phase of HASH handle is tested to check whether or not 00929 * the Peripheral has already been initialized. 00930 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 00931 * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able 00932 * to manage the ending buffer with a length in bytes not a multiple of 4. 00933 * @param hhash HASH handle. 00934 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00935 * @param Size length of the input buffer in bytes, must be a multiple of 4. 00936 * @retval HAL status 00937 */ 00938 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 00939 { 00940 return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); 00941 } 00942 00943 /** 00944 * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API. 00945 * @note Digest is available in pOutBuffer. 00946 * @param hhash HASH handle. 00947 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00948 * @param Size length of the input buffer in bytes. 00949 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 00950 * @retval HAL status 00951 */ 00952 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 00953 uint8_t *pOutBuffer) 00954 { 00955 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5); 00956 } 00957 00958 /** 00959 * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then 00960 * read the computed digest in interruption mode. 00961 * @note Digest is available in pOutBuffer. 00962 * @param hhash HASH handle. 00963 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00964 * @param Size length of the input buffer in bytes. 00965 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 00966 * @retval HAL status 00967 */ 00968 HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 00969 uint8_t *pOutBuffer) 00970 { 00971 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1); 00972 } 00973 00974 00975 /** 00976 * @brief If not already done, initialize the HASH peripheral in SHA1 mode then 00977 * processes pInBuffer in interruption mode. 00978 * @note Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed 00979 * several input buffers back-to-back to the Peripheral that will yield a single 00980 * HASH signature once all buffers have been entered. Wrap-up of input 00981 * buffers feeding and retrieval of digest is done by a call to 00982 * HAL_HASH_SHA1_Accmlt_End_IT(). 00983 * @note Field hhash->Phase of HASH handle is tested to check whether or not 00984 * the Peripheral has already been initialized. 00985 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 00986 * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able 00987 * to manage the ending buffer with a length in bytes not a multiple of 4. 00988 * @param hhash HASH handle. 00989 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 00990 * @param Size length of the input buffer in bytes, must be a multiple of 4. 00991 * @retval HAL status 00992 */ 00993 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 00994 { 00995 return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); 00996 } 00997 00998 /** 00999 * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API. 01000 * @note Digest is available in pOutBuffer. 01001 * @param hhash HASH handle. 01002 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 01003 * @param Size length of the input buffer in bytes. 01004 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 01005 * @retval HAL status 01006 */ 01007 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 01008 uint8_t *pOutBuffer) 01009 { 01010 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1); 01011 } 01012 01013 /** 01014 * @brief Handle HASH interrupt request. 01015 * @param hhash HASH handle. 01016 * @note HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well. 01017 * @note In case of error reported during the HASH interruption processing, 01018 * HAL_HASH_ErrorCallback() API is called so that user code can 01019 * manage the error. The error type is available in hhash->Status field. 01020 * @retval None 01021 */ 01022 void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash) 01023 { 01024 hhash->Status = HASH_IT(hhash); 01025 if (hhash->Status != HAL_OK) 01026 { 01027 hhash->ErrorCode |= HAL_HASH_ERROR_IT; 01028 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 01029 hhash->ErrorCallback(hhash); 01030 #else 01031 HAL_HASH_ErrorCallback(hhash); 01032 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 01033 /* After error handling by code user, reset HASH handle HAL status */ 01034 hhash->Status = HAL_OK; 01035 } 01036 } 01037 01038 /** 01039 * @} 01040 */ 01041 01042 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode 01043 * @brief HASH processing functions using DMA mode. 01044 * 01045 @verbatim 01046 =============================================================================== 01047 ##### DMA mode HASH processing functions ##### 01048 =============================================================================== 01049 [..] This section provides functions allowing to calculate in DMA mode 01050 the hash value using one of the following algorithms: 01051 (+) MD5 01052 (++) HAL_HASH_MD5_Start_DMA() 01053 (++) HAL_HASH_MD5_Finish() 01054 (+) SHA1 01055 (++) HAL_HASH_SHA1_Start_DMA() 01056 (++) HAL_HASH_SHA1_Finish() 01057 01058 [..] When resorting to DMA mode to enter the data in the Peripheral, user must resort 01059 to HAL_HASH_xxx_Start_DMA() then read the resulting digest with 01060 HAL_HASH_xxx_Finish(). 01061 [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before 01062 the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be 01063 reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally 01064 retrieved thanks to HAL_HASH_xxx_Finish(). 01065 01066 @endverbatim 01067 * @{ 01068 */ 01069 01070 /** 01071 * @brief Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer 01072 * to feed the input buffer to the Peripheral. 01073 * @note Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must 01074 * be called to retrieve the computed digest. 01075 * @param hhash HASH handle. 01076 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 01077 * @param Size length of the input buffer in bytes. 01078 * @retval HAL status 01079 */ 01080 HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 01081 { 01082 return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); 01083 } 01084 01085 /** 01086 * @brief Return the computed digest in MD5 mode. 01087 * @note The API waits for DCIS to be set then reads the computed digest. 01088 * @note HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in 01089 * HMAC MD5 mode. 01090 * @param hhash HASH handle. 01091 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 01092 * @param Timeout Timeout value. 01093 * @retval HAL status 01094 */ 01095 HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) 01096 { 01097 return HASH_Finish(hhash, pOutBuffer, Timeout); 01098 } 01099 01100 /** 01101 * @brief Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer 01102 * to feed the input buffer to the Peripheral. 01103 * @note Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must 01104 * be called to retrieve the computed digest. 01105 * @param hhash HASH handle. 01106 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 01107 * @param Size length of the input buffer in bytes. 01108 * @retval HAL status 01109 */ 01110 HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 01111 { 01112 return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); 01113 } 01114 01115 01116 /** 01117 * @brief Return the computed digest in SHA1 mode. 01118 * @note The API waits for DCIS to be set then reads the computed digest. 01119 * @note HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in 01120 * HMAC SHA1 mode. 01121 * @param hhash HASH handle. 01122 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 01123 * @param Timeout Timeout value. 01124 * @retval HAL status 01125 */ 01126 HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) 01127 { 01128 return HASH_Finish(hhash, pOutBuffer, Timeout); 01129 } 01130 01131 /** 01132 * @} 01133 */ 01134 01135 /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode 01136 * @brief HMAC processing functions using polling mode. 01137 * 01138 @verbatim 01139 =============================================================================== 01140 ##### Polling mode HMAC processing functions ##### 01141 =============================================================================== 01142 [..] This section provides functions allowing to calculate in polling mode 01143 the HMAC value using one of the following algorithms: 01144 (+) MD5 01145 (++) HAL_HMAC_MD5_Start() 01146 (+) SHA1 01147 (++) HAL_HMAC_SHA1_Start() 01148 01149 01150 @endverbatim 01151 * @{ 01152 */ 01153 01154 /** 01155 * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then 01156 * read the computed digest. 01157 * @note Digest is available in pOutBuffer. 01158 * @note Same key is used for the inner and the outer hash functions; pointer to key and 01159 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 01160 * @param hhash HASH handle. 01161 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 01162 * @param Size length of the input buffer in bytes. 01163 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 01164 * @param Timeout Timeout value. 01165 * @retval HAL status 01166 */ 01167 HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 01168 uint32_t Timeout) 01169 { 01170 return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); 01171 } 01172 01173 /** 01174 * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then 01175 * read the computed digest. 01176 * @note Digest is available in pOutBuffer. 01177 * @note Same key is used for the inner and the outer hash functions; pointer to key and 01178 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 01179 * @param hhash HASH handle. 01180 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 01181 * @param Size length of the input buffer in bytes. 01182 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 01183 * @param Timeout Timeout value. 01184 * @retval HAL status 01185 */ 01186 HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 01187 uint32_t Timeout) 01188 { 01189 return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); 01190 } 01191 01192 /** 01193 * @} 01194 */ 01195 01196 01197 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode 01198 * @brief HMAC processing functions using interrupt mode. 01199 * 01200 @verbatim 01201 =============================================================================== 01202 ##### Interrupt mode HMAC processing functions ##### 01203 =============================================================================== 01204 [..] This section provides functions allowing to calculate in interrupt mode 01205 the HMAC value using one of the following algorithms: 01206 (+) MD5 01207 (++) HAL_HMAC_MD5_Start_IT() 01208 (+) SHA1 01209 (++) HAL_HMAC_SHA1_Start_IT() 01210 01211 @endverbatim 01212 * @{ 01213 */ 01214 01215 01216 /** 01217 * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then 01218 * read the computed digest in interrupt mode. 01219 * @note Digest is available in pOutBuffer. 01220 * @note Same key is used for the inner and the outer hash functions; pointer to key and 01221 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 01222 * @param hhash HASH handle. 01223 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 01224 * @param Size length of the input buffer in bytes. 01225 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. 01226 * @retval HAL status 01227 */ 01228 HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 01229 uint8_t *pOutBuffer) 01230 { 01231 return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5); 01232 } 01233 01234 /** 01235 * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then 01236 * read the computed digest in interrupt mode. 01237 * @note Digest is available in pOutBuffer. 01238 * @note Same key is used for the inner and the outer hash functions; pointer to key and 01239 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 01240 * @param hhash HASH handle. 01241 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 01242 * @param Size length of the input buffer in bytes. 01243 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. 01244 * @retval HAL status 01245 */ 01246 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, 01247 uint8_t *pOutBuffer) 01248 { 01249 return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1); 01250 } 01251 01252 /** 01253 * @} 01254 */ 01255 01256 01257 01258 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode 01259 * @brief HMAC processing functions using DMA modes. 01260 * 01261 @verbatim 01262 =============================================================================== 01263 ##### DMA mode HMAC processing functions ##### 01264 =============================================================================== 01265 [..] This section provides functions allowing to calculate in DMA mode 01266 the HMAC value using one of the following algorithms: 01267 (+) MD5 01268 (++) HAL_HMAC_MD5_Start_DMA() 01269 (+) SHA1 01270 (++) HAL_HMAC_SHA1_Start_DMA() 01271 01272 [..] When resorting to DMA mode to enter the data in the Peripheral for HMAC processing, 01273 user must resort to HAL_HMAC_xxx_Start_DMA() then read the resulting digest 01274 with HAL_HASH_xxx_Finish(). 01275 01276 @endverbatim 01277 * @{ 01278 */ 01279 01280 01281 /** 01282 * @brief Initialize the HASH peripheral in HMAC MD5 mode then initiate the required 01283 * DMA transfers to feed the key and the input buffer to the Peripheral. 01284 * @note Once the DMA transfers are finished (indicated by hhash->State set back 01285 * to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve 01286 * the computed digest. 01287 * @note Same key is used for the inner and the outer hash functions; pointer to key and 01288 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 01289 * @note If MDMAT bit is set before calling this function (multi-buffer 01290 * HASH processing case), the input buffer size (in bytes) must be 01291 * a multiple of 4 otherwise, the HASH digest computation is corrupted. 01292 * For the processing of the last buffer of the thread, MDMAT bit must 01293 * be reset and the buffer length (in bytes) doesn't have to be a 01294 * multiple of 4. 01295 * @param hhash HASH handle. 01296 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 01297 * @param Size length of the input buffer in bytes. 01298 * @retval HAL status 01299 */ 01300 HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 01301 { 01302 return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); 01303 } 01304 01305 01306 /** 01307 * @brief Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required 01308 * DMA transfers to feed the key and the input buffer to the Peripheral. 01309 * @note Once the DMA transfers are finished (indicated by hhash->State set back 01310 * to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve 01311 * the computed digest. 01312 * @note Same key is used for the inner and the outer hash functions; pointer to key and 01313 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 01314 * @note If MDMAT bit is set before calling this function (multi-buffer 01315 * HASH processing case), the input buffer size (in bytes) must be 01316 * a multiple of 4 otherwise, the HASH digest computation is corrupted. 01317 * For the processing of the last buffer of the thread, MDMAT bit must 01318 * be reset and the buffer length (in bytes) doesn't have to be a 01319 * multiple of 4. 01320 * @param hhash HASH handle. 01321 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 01322 * @param Size length of the input buffer in bytes. 01323 * @retval HAL status 01324 */ 01325 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 01326 { 01327 return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); 01328 } 01329 01330 /** 01331 * @} 01332 */ 01333 01334 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions 01335 * @brief Peripheral State functions. 01336 * 01337 @verbatim 01338 =============================================================================== 01339 ##### Peripheral State methods ##### 01340 =============================================================================== 01341 [..] 01342 This section permits to get in run-time the state and the peripheral handle 01343 status of the peripheral: 01344 (+) HAL_HASH_GetState() 01345 (+) HAL_HASH_GetStatus() 01346 01347 [..] 01348 Additionally, this subsection provides functions allowing to save and restore 01349 the HASH or HMAC processing context in case of calculation suspension: 01350 (+) HAL_HASH_ContextSaving() 01351 (+) HAL_HASH_ContextRestoring() 01352 01353 [..] 01354 This subsection provides functions allowing to suspend the HASH processing 01355 (+) when input are fed to the Peripheral by software 01356 (++) HAL_HASH_SwFeed_ProcessSuspend() 01357 (+) when input are fed to the Peripheral by DMA 01358 (++) HAL_HASH_DMAFeed_ProcessSuspend() 01359 01360 01361 01362 @endverbatim 01363 * @{ 01364 */ 01365 01366 /** 01367 * @brief Return the HASH handle state. 01368 * @note The API yields the current state of the handle (BUSY, READY,...). 01369 * @param hhash HASH handle. 01370 * @retval HAL HASH state 01371 */ 01372 HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash) 01373 { 01374 return hhash->State; 01375 } 01376 01377 01378 /** 01379 * @brief Return the HASH HAL status. 01380 * @note The API yields the HAL status of the handle: it is the result of the 01381 * latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT). 01382 * @param hhash HASH handle. 01383 * @retval HAL status 01384 */ 01385 HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash) 01386 { 01387 return hhash->Status; 01388 } 01389 01390 /** 01391 * @brief Save the HASH context in case of processing suspension. 01392 * @param hhash HASH handle. 01393 * @param pMemBuffer pointer to the memory buffer where the HASH context 01394 * is saved. 01395 * @note The IMR, STR, CR then all the CSR registers are saved 01396 * in that order. Only the r/w bits are read to be restored later on. 01397 * @note By default, all the context swap registers (there are 01398 * HASH_NUMBER_OF_CSR_REGISTERS of those) are saved. 01399 * @note pMemBuffer points to a buffer allocated by the user. The buffer size 01400 * must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long. 01401 * @retval None 01402 */ 01403 void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer) 01404 { 01405 uint32_t mem_ptr = (uint32_t)pMemBuffer; 01406 uint32_t csr_ptr = (uint32_t)HASH->CSR; 01407 uint32_t i; 01408 01409 /* Prevent unused argument(s) compilation warning */ 01410 UNUSED(hhash); 01411 01412 /* Save IMR register content */ 01413 *(uint32_t *)(mem_ptr) = READ_BIT(HASH->IMR, HASH_IT_DINI | HASH_IT_DCI); 01414 mem_ptr += 4U; 01415 /* Save STR register content */ 01416 *(uint32_t *)(mem_ptr) = READ_BIT(HASH->STR, HASH_STR_NBLW); 01417 mem_ptr += 4U; 01418 /* Save CR register content */ 01419 *(uint32_t *)(mem_ptr) = READ_BIT(HASH->CR, HASH_CR_DMAE | HASH_CR_DATATYPE | HASH_CR_MODE | HASH_CR_ALGO | 01420 HASH_CR_LKEY | HASH_CR_MDMAT); 01421 mem_ptr += 4U; 01422 /* By default, save all CSRs registers */ 01423 for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--) 01424 { 01425 *(uint32_t *)(mem_ptr) = *(uint32_t *)(csr_ptr); 01426 mem_ptr += 4U; 01427 csr_ptr += 4U; 01428 } 01429 } 01430 01431 01432 /** 01433 * @brief Restore the HASH context in case of processing resumption. 01434 * @param hhash HASH handle. 01435 * @param pMemBuffer pointer to the memory buffer where the HASH context 01436 * is stored. 01437 * @note The IMR, STR, CR then all the CSR registers are restored 01438 * in that order. Only the r/w bits are restored. 01439 * @note By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS 01440 * of those) are restored (all of them have been saved by default 01441 * beforehand). 01442 * @retval None 01443 */ 01444 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer) 01445 { 01446 uint32_t mem_ptr = (uint32_t)pMemBuffer; 01447 uint32_t csr_ptr = (uint32_t)HASH->CSR; 01448 uint32_t i; 01449 01450 /* Prevent unused argument(s) compilation warning */ 01451 UNUSED(hhash); 01452 01453 /* Restore IMR register content */ 01454 WRITE_REG(HASH->IMR, (*(uint32_t *)(mem_ptr))); 01455 mem_ptr += 4U; 01456 /* Restore STR register content */ 01457 WRITE_REG(HASH->STR, (*(uint32_t *)(mem_ptr))); 01458 mem_ptr += 4U; 01459 /* Restore CR register content */ 01460 WRITE_REG(HASH->CR, (*(uint32_t *)(mem_ptr))); 01461 mem_ptr += 4U; 01462 01463 /* Reset the HASH processor before restoring the Context 01464 Swap Registers (CSR) */ 01465 __HAL_HASH_INIT(); 01466 01467 /* By default, restore all CSR registers */ 01468 for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--) 01469 { 01470 WRITE_REG((*(uint32_t *)(csr_ptr)), (*(uint32_t *)(mem_ptr))); 01471 mem_ptr += 4U; 01472 csr_ptr += 4U; 01473 } 01474 } 01475 01476 01477 /** 01478 * @brief Initiate HASH processing suspension when in polling or interruption mode. 01479 * @param hhash HASH handle. 01480 * @note Set the handle field SuspendRequest to the appropriate value so that 01481 * the on-going HASH processing is suspended as soon as the required 01482 * conditions are met. Note that the actual suspension is carried out 01483 * by the functions HASH_WriteData() in polling mode and HASH_IT() in 01484 * interruption mode. 01485 * @retval None 01486 */ 01487 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) 01488 { 01489 /* Set Handle Suspend Request field */ 01490 hhash->SuspendRequest = HAL_HASH_SUSPEND; 01491 } 01492 01493 /** 01494 * @brief Suspend the HASH processing when in DMA mode. 01495 * @param hhash HASH handle. 01496 * @note When suspension attempt occurs at the very end of a DMA transfer and 01497 * all the data have already been entered in the Peripheral, hhash->State is 01498 * set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is 01499 * recommended to wrap-up the processing in reading the digest as usual. 01500 * @retval HAL status 01501 */ 01502 HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) 01503 { 01504 uint32_t tmp_remaining_DMATransferSize_inWords; 01505 uint32_t tmp_initial_DMATransferSize_inWords; 01506 uint32_t tmp_words_already_pushed; 01507 01508 if (hhash->State == HAL_HASH_STATE_READY) 01509 { 01510 return HAL_ERROR; 01511 } 01512 else 01513 { 01514 01515 /* Make sure there is enough time to suspend the processing */ 01516 tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR; 01517 01518 if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT) 01519 { 01520 /* No suspension attempted since almost to the end of the transferred data. */ 01521 /* Best option for user code is to wrap up low priority message hashing */ 01522 return HAL_ERROR; 01523 } 01524 01525 /* Wait for BUSY flag to be reset */ 01526 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 01527 { 01528 return HAL_TIMEOUT; 01529 } 01530 01531 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET) 01532 { 01533 return HAL_ERROR; 01534 } 01535 01536 /* Wait for BUSY flag to be set */ 01537 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK) 01538 { 01539 return HAL_TIMEOUT; 01540 } 01541 /* Disable DMA channel */ 01542 /* Note that the Abort function will 01543 - Clear the transfer error flags 01544 - Unlock 01545 - Set the State 01546 */ 01547 if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK) 01548 { 01549 return HAL_ERROR; 01550 } 01551 01552 /* Clear DMAE bit */ 01553 CLEAR_BIT(HASH->CR, HASH_CR_DMAE); 01554 01555 /* Wait for BUSY flag to be reset */ 01556 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 01557 { 01558 return HAL_TIMEOUT; 01559 } 01560 01561 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET) 01562 { 01563 return HAL_ERROR; 01564 } 01565 01566 /* At this point, DMA interface is disabled and no transfer is on-going */ 01567 /* Retrieve from the DMA handle how many words remain to be written */ 01568 tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR; 01569 01570 if (tmp_remaining_DMATransferSize_inWords == 0U) 01571 { 01572 /* All the DMA transfer is actually done. Suspension occurred at the very end 01573 of the transfer. Either the digest computation is about to start (HASH case) 01574 or processing is about to move from one step to another (HMAC case). 01575 In both cases, the processing can't be suspended at this point. It is 01576 safer to 01577 - retrieve the low priority block digest before starting the high 01578 priority block processing (HASH case) 01579 - re-attempt a new suspension (HMAC case) 01580 */ 01581 return HAL_ERROR; 01582 } 01583 else 01584 { 01585 01586 /* Compute how many words were supposed to be transferred by DMA */ 01587 tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount % 4U) != 0U) ? \ 01588 ((hhash->HashInCount + 3U) / 4U) : (hhash->HashInCount / 4U)); 01589 01590 /* If discrepancy between the number of words reported by DMA Peripheral and 01591 the numbers of words entered as reported by HASH Peripheral, correct it */ 01592 /* tmp_words_already_pushed reflects the number of words that were already pushed before 01593 the start of DMA transfer (multi-buffer processing case) */ 01594 tmp_words_already_pushed = hhash->NbWordsAlreadyPushed; 01595 if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - \ 01596 tmp_remaining_DMATransferSize_inWords) % 16U) != HASH_NBW_PUSHED()) 01597 { 01598 tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */ 01599 } 01600 01601 /* Accordingly, update the input pointer that points at the next word to be 01602 transferred to the Peripheral by DMA */ 01603 hhash->pHashInBuffPtr += 4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ; 01604 01605 /* And store in HashInCount the remaining size to transfer (in bytes) */ 01606 hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords; 01607 01608 } 01609 01610 /* Set State as suspended */ 01611 hhash->State = HAL_HASH_STATE_SUSPENDED; 01612 01613 return HAL_OK; 01614 01615 } 01616 } 01617 01618 /** 01619 * @brief Return the HASH handle error code. 01620 * @param hhash pointer to a HASH_HandleTypeDef structure. 01621 * @retval HASH Error Code 01622 */ 01623 uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash) 01624 { 01625 /* Return HASH Error Code */ 01626 return hhash->ErrorCode; 01627 } 01628 /** 01629 * @} 01630 */ 01631 01632 01633 /** 01634 * @} 01635 */ 01636 01637 /** @defgroup HASH_Private_Functions HASH Private Functions 01638 * @{ 01639 */ 01640 01641 /** 01642 * @brief DMA HASH Input Data transfer completion callback. 01643 * @param hdma DMA handle. 01644 * @note In case of HMAC processing, HASH_DMAXferCplt() initiates 01645 * the next DMA transfer for the following HMAC step. 01646 * @retval None 01647 */ 01648 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma) 01649 { 01650 HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 01651 uint32_t inputaddr; 01652 uint32_t buffersize; 01653 HAL_StatusTypeDef status = HAL_OK; 01654 01655 if (hhash->State != HAL_HASH_STATE_SUSPENDED) 01656 { 01657 01658 /* Disable the DMA transfer */ 01659 CLEAR_BIT(HASH->CR, HASH_CR_DMAE); 01660 01661 if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U) 01662 { 01663 /* If no HMAC processing, input data transfer is now over */ 01664 01665 /* Change the HASH state to ready */ 01666 hhash->State = HAL_HASH_STATE_READY; 01667 01668 /* Call Input data transfer complete call back */ 01669 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 01670 hhash->InCpltCallback(hhash); 01671 #else 01672 HAL_HASH_InCpltCallback(hhash); 01673 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 01674 01675 } 01676 else 01677 { 01678 /* HMAC processing: depending on the current HMAC step and whether or 01679 not multi-buffer processing is on-going, the next step is initiated 01680 and MDMAT bit is set. */ 01681 01682 01683 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3) 01684 { 01685 /* This is the end of HMAC processing */ 01686 01687 /* Change the HASH state to ready */ 01688 hhash->State = HAL_HASH_STATE_READY; 01689 01690 /* Call Input data transfer complete call back 01691 (note that the last DMA transfer was that of the key 01692 for the outer HASH operation). */ 01693 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 01694 hhash->InCpltCallback(hhash); 01695 #else 01696 HAL_HASH_InCpltCallback(hhash); 01697 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 01698 01699 return; 01700 } 01701 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) 01702 { 01703 inputaddr = (uint32_t)hhash->pHashMsgBuffPtr; /* DMA transfer start address */ 01704 buffersize = hhash->HashBuffSize; /* DMA transfer size (in bytes) */ 01705 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */ 01706 01707 /* In case of suspension request, save the new starting parameters */ 01708 hhash->HashInCount = hhash->HashBuffSize; /* Initial DMA transfer size (in bytes) */ 01709 hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr ; /* DMA transfer start address */ 01710 01711 hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */ 01712 /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */ 01713 if (hhash->DigestCalculationDisable != RESET) 01714 { 01715 /* Digest calculation is disabled: Step 2 must start with MDMAT bit set, 01716 no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */ 01717 __HAL_HASH_SET_MDMAT(); 01718 } 01719 } 01720 else /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/ 01721 { 01722 if (hhash->DigestCalculationDisable != RESET) 01723 { 01724 /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral 01725 (case of multi-buffer HMAC processing): 01726 DCAL must not be set. 01727 Phase remains in Step 2, MDMAT remains set at this point. 01728 Change the HASH state to ready and call Input data transfer complete call back. */ 01729 hhash->State = HAL_HASH_STATE_READY; 01730 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 01731 hhash->InCpltCallback(hhash); 01732 #else 01733 HAL_HASH_InCpltCallback(hhash); 01734 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 01735 return ; 01736 } 01737 else 01738 { 01739 /* Digest calculation is not disabled (case of single buffer input or last buffer 01740 of multi-buffer HMAC processing) */ 01741 inputaddr = (uint32_t)hhash->Init.pKey; /* DMA transfer start address */ 01742 buffersize = hhash->Init.KeySize; /* DMA transfer size (in bytes) */ 01743 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */ 01744 /* In case of suspension request, save the new starting parameters */ 01745 hhash->HashInCount = hhash->Init.KeySize; /* Initial size for second DMA transfer (input data) */ 01746 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* address passed to DMA, now entering data message */ 01747 01748 hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */ 01749 } 01750 } 01751 01752 /* Configure the Number of valid bits in last word of the message */ 01753 __HAL_HASH_SET_NBVALIDBITS(buffersize); 01754 01755 /* Set the HASH DMA transfer completion call back */ 01756 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; 01757 01758 /* Enable the DMA In DMA stream */ 01759 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \ 01760 (((buffersize % 4U) != 0U) ? ((buffersize + (4U - (buffersize % 4U))) / 4U) : \ 01761 (buffersize / 4U))); 01762 01763 /* Enable DMA requests */ 01764 SET_BIT(HASH->CR, HASH_CR_DMAE); 01765 01766 /* Return function status */ 01767 if (status != HAL_OK) 01768 { 01769 /* Update HASH state machine to error */ 01770 hhash->State = HAL_HASH_STATE_ERROR; 01771 } 01772 else 01773 { 01774 /* Change HASH state */ 01775 hhash->State = HAL_HASH_STATE_BUSY; 01776 } 01777 } 01778 } 01779 01780 return; 01781 } 01782 01783 /** 01784 * @brief DMA HASH communication error callback. 01785 * @param hdma DMA handle. 01786 * @note HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that 01787 * can contain user code to manage the error. 01788 * @retval None 01789 */ 01790 static void HASH_DMAError(DMA_HandleTypeDef *hdma) 01791 { 01792 HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; 01793 01794 if (hhash->State != HAL_HASH_STATE_SUSPENDED) 01795 { 01796 hhash->ErrorCode |= HAL_HASH_ERROR_DMA; 01797 /* Set HASH state to ready to prevent any blocking issue in user code 01798 present in HAL_HASH_ErrorCallback() */ 01799 hhash->State = HAL_HASH_STATE_READY; 01800 /* Set HASH handle status to error */ 01801 hhash->Status = HAL_ERROR; 01802 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 01803 hhash->ErrorCallback(hhash); 01804 #else 01805 HAL_HASH_ErrorCallback(hhash); 01806 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 01807 /* After error handling by code user, reset HASH handle HAL status */ 01808 hhash->Status = HAL_OK; 01809 01810 } 01811 } 01812 01813 /** 01814 * @brief Feed the input buffer to the HASH Peripheral. 01815 * @param hhash HASH handle. 01816 * @param pInBuffer pointer to input buffer. 01817 * @param Size the size of input buffer in bytes. 01818 * @note HASH_WriteData() regularly reads hhash->SuspendRequest to check whether 01819 * or not the HASH processing must be suspended. If this is the case, the 01820 * processing is suspended when possible and the Peripheral feeding point reached at 01821 * suspension time is stored in the handle for resumption later on. 01822 * @retval HAL status 01823 */ 01824 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) 01825 { 01826 uint32_t buffercounter; 01827 __IO uint32_t inputaddr = (uint32_t) pInBuffer; 01828 01829 for (buffercounter = 0U; buffercounter < Size; buffercounter += 4U) 01830 { 01831 /* Write input data 4 bytes at a time */ 01832 HASH->DIN = *(uint32_t *)inputaddr; 01833 inputaddr += 4U; 01834 01835 /* If the suspension flag has been raised and if the processing is not about 01836 to end, suspend processing */ 01837 if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter + 4U) < Size)) 01838 { 01839 /* wait for flag BUSY not set before Wait for DINIS = 1*/ 01840 if (buffercounter >= 64U) 01841 { 01842 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 01843 { 01844 return HAL_TIMEOUT; 01845 } 01846 } 01847 /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free 01848 in the input buffer */ 01849 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) 01850 { 01851 /* Reset SuspendRequest */ 01852 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; 01853 01854 /* Depending whether the key or the input data were fed to the Peripheral, the feeding point 01855 reached at suspension time is not saved in the same handle fields */ 01856 if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)) 01857 { 01858 /* Save current reading and writing locations of Input and Output buffers */ 01859 hhash->pHashInBuffPtr = (uint8_t *)inputaddr; 01860 /* Save the number of bytes that remain to be processed at this point */ 01861 hhash->HashInCount = Size - (buffercounter + 4U); 01862 } 01863 else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)) 01864 { 01865 /* Save current reading and writing locations of Input and Output buffers */ 01866 hhash->pHashKeyBuffPtr = (uint8_t *)inputaddr; 01867 /* Save the number of bytes that remain to be processed at this point */ 01868 hhash->HashKeyCount = Size - (buffercounter + 4U); 01869 } 01870 else 01871 { 01872 /* Unexpected phase: unlock process and report error */ 01873 hhash->State = HAL_HASH_STATE_READY; 01874 __HAL_UNLOCK(hhash); 01875 return HAL_ERROR; 01876 } 01877 01878 /* Set the HASH state to Suspended and exit to stop entering data */ 01879 hhash->State = HAL_HASH_STATE_SUSPENDED; 01880 01881 return HAL_OK; 01882 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) */ 01883 } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */ 01884 } /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4) */ 01885 01886 /* At this point, all the data have been entered to the Peripheral: exit */ 01887 return HAL_OK; 01888 } 01889 01890 /** 01891 * @brief Retrieve the message digest. 01892 * @param pMsgDigest pointer to the computed digest. 01893 * @param Size message digest size in bytes. 01894 * @retval None 01895 */ 01896 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size) 01897 { 01898 uint32_t msgdigest = (uint32_t)pMsgDigest; 01899 01900 switch (Size) 01901 { 01902 /* Read the message digest */ 01903 case 16: /* MD5 */ 01904 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); 01905 msgdigest += 4U; 01906 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); 01907 msgdigest += 4U; 01908 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); 01909 msgdigest += 4U; 01910 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); 01911 break; 01912 case 20: /* SHA1 */ 01913 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); 01914 msgdigest += 4U; 01915 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); 01916 msgdigest += 4U; 01917 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); 01918 msgdigest += 4U; 01919 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); 01920 msgdigest += 4U; 01921 *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]); 01922 break; 01923 case 28: /* SHA224 */ 01924 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); 01925 msgdigest += 4U; 01926 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); 01927 msgdigest += 4U; 01928 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); 01929 msgdigest += 4U; 01930 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); 01931 msgdigest += 4U; 01932 *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]); 01933 msgdigest += 4U; 01934 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]); 01935 msgdigest += 4U; 01936 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]); 01937 break; 01938 case 32: /* SHA256 */ 01939 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); 01940 msgdigest += 4U; 01941 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); 01942 msgdigest += 4U; 01943 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); 01944 msgdigest += 4U; 01945 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); 01946 msgdigest += 4U; 01947 *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]); 01948 msgdigest += 4U; 01949 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]); 01950 msgdigest += 4U; 01951 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]); 01952 msgdigest += 4U; 01953 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[7]); 01954 break; 01955 default: 01956 break; 01957 } 01958 } 01959 01960 01961 01962 /** 01963 * @brief Handle HASH processing Timeout. 01964 * @param hhash HASH handle. 01965 * @param Flag specifies the HASH flag to check. 01966 * @param Status the Flag status (SET or RESET). 01967 * @param Timeout Timeout duration. 01968 * @retval HAL status 01969 */ 01970 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, 01971 uint32_t Timeout) 01972 { 01973 uint32_t tickstart = HAL_GetTick(); 01974 01975 /* Wait until flag is set */ 01976 if (Status == RESET) 01977 { 01978 while (__HAL_HASH_GET_FLAG(Flag) == RESET) 01979 { 01980 /* Check for the Timeout */ 01981 if (Timeout != HAL_MAX_DELAY) 01982 { 01983 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) 01984 { 01985 /* Set State to Ready to be able to restart later on */ 01986 hhash->State = HAL_HASH_STATE_READY; 01987 /* Store time out issue in handle status */ 01988 hhash->Status = HAL_TIMEOUT; 01989 01990 /* Process Unlocked */ 01991 __HAL_UNLOCK(hhash); 01992 01993 return HAL_TIMEOUT; 01994 } 01995 } 01996 } 01997 } 01998 else 01999 { 02000 while (__HAL_HASH_GET_FLAG(Flag) != RESET) 02001 { 02002 /* Check for the Timeout */ 02003 if (Timeout != HAL_MAX_DELAY) 02004 { 02005 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) 02006 { 02007 /* Set State to Ready to be able to restart later on */ 02008 hhash->State = HAL_HASH_STATE_READY; 02009 /* Store time out issue in handle status */ 02010 hhash->Status = HAL_TIMEOUT; 02011 02012 /* Process Unlocked */ 02013 __HAL_UNLOCK(hhash); 02014 02015 return HAL_TIMEOUT; 02016 } 02017 } 02018 } 02019 } 02020 return HAL_OK; 02021 } 02022 02023 02024 /** 02025 * @brief HASH processing in interruption mode. 02026 * @param hhash HASH handle. 02027 * @note HASH_IT() regularly reads hhash->SuspendRequest to check whether 02028 * or not the HASH processing must be suspended. If this is the case, the 02029 * processing is suspended when possible and the Peripheral feeding point reached at 02030 * suspension time is stored in the handle for resumption later on. 02031 * @retval HAL status 02032 */ 02033 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) 02034 { 02035 if (hhash->State == HAL_HASH_STATE_BUSY) 02036 { 02037 /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */ 02038 if (hhash->HashITCounter == 0U) 02039 { 02040 /* Disable Interrupts */ 02041 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 02042 /* HASH state set back to Ready to prevent any issue in user code 02043 present in HAL_HASH_ErrorCallback() */ 02044 hhash->State = HAL_HASH_STATE_READY; 02045 return HAL_ERROR; 02046 } 02047 else if (hhash->HashITCounter == 1U) 02048 { 02049 /* This is the first call to HASH_IT, the first input data are about to be 02050 entered in the Peripheral. A specific processing is carried out at this point to 02051 start-up the processing. */ 02052 hhash->HashITCounter = 2U; 02053 } 02054 else 02055 { 02056 /* Cruise speed reached, HashITCounter remains equal to 3 until the end of 02057 the HASH processing or the end of the current step for HMAC processing. */ 02058 hhash->HashITCounter = 3U; 02059 } 02060 02061 /* If digest is ready */ 02062 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS)) 02063 { 02064 /* Read the digest */ 02065 HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH()); 02066 02067 /* Disable Interrupts */ 02068 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 02069 /* Change the HASH state */ 02070 hhash->State = HAL_HASH_STATE_READY; 02071 /* Reset HASH state machine */ 02072 hhash->Phase = HAL_HASH_PHASE_READY; 02073 /* Call digest computation complete call back */ 02074 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 02075 hhash->DgstCpltCallback(hhash); 02076 #else 02077 HAL_HASH_DgstCpltCallback(hhash); 02078 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 02079 02080 return HAL_OK; 02081 } 02082 02083 /* If Peripheral ready to accept new data */ 02084 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) 02085 { 02086 02087 /* If the suspension flag has been raised and if the processing is not about 02088 to end, suspend processing */ 02089 if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND)) 02090 { 02091 /* Disable Interrupts */ 02092 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 02093 02094 /* Reset SuspendRequest */ 02095 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; 02096 02097 /* Change the HASH state */ 02098 hhash->State = HAL_HASH_STATE_SUSPENDED; 02099 02100 return HAL_OK; 02101 } 02102 02103 /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and 02104 check whether the digest calculation has been triggered */ 02105 if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) 02106 { 02107 /* Call Input data transfer complete call back 02108 (called at the end of each step for HMAC) */ 02109 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 02110 hhash->InCpltCallback(hhash); 02111 #else 02112 HAL_HASH_InCpltCallback(hhash); 02113 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 02114 02115 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) 02116 { 02117 /* Wait until Peripheral is not busy anymore */ 02118 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 02119 { 02120 /* Disable Interrupts */ 02121 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 02122 return HAL_TIMEOUT; 02123 } 02124 /* Initialization start for HMAC STEP 2 */ 02125 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */ 02126 __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); /* Set NBLW for the input message */ 02127 hhash->HashInCount = hhash->HashBuffSize; /* Set the input data size (in bytes) */ 02128 hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr; /* Set the input data address */ 02129 hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start 02130 of a new phase */ 02131 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */ 02132 } 02133 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) 02134 { 02135 /* Wait until Peripheral is not busy anymore */ 02136 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) 02137 { 02138 /* Disable Interrupts */ 02139 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 02140 return HAL_TIMEOUT; 02141 } 02142 /* Initialization start for HMAC STEP 3 */ 02143 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */ 02144 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); /* Set NBLW for the key */ 02145 hhash->HashInCount = hhash->Init.KeySize; /* Set the key size (in bytes) */ 02146 hhash->pHashInBuffPtr = hhash->Init.pKey; /* Set the key address */ 02147 hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start 02148 of a new phase */ 02149 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */ 02150 } 02151 else 02152 { 02153 /* Nothing to do */ 02154 } 02155 } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */ 02156 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/ 02157 02158 /* Return function status */ 02159 return HAL_OK; 02160 } 02161 else 02162 { 02163 return HAL_BUSY; 02164 } 02165 } 02166 02167 02168 /** 02169 * @brief Write a block of data in HASH Peripheral in interruption mode. 02170 * @param hhash HASH handle. 02171 * @note HASH_Write_Block_Data() is called under interruption by HASH_IT(). 02172 * @retval HAL status 02173 */ 02174 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash) 02175 { 02176 uint32_t inputaddr; 02177 uint32_t buffercounter; 02178 uint32_t inputcounter; 02179 uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED; 02180 02181 /* If there are more than 64 bytes remaining to be entered */ 02182 if (hhash->HashInCount > 64U) 02183 { 02184 inputaddr = (uint32_t)hhash->pHashInBuffPtr; 02185 /* Write the Input block in the Data IN register 02186 (16 32-bit words, or 64 bytes are entered) */ 02187 for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U) 02188 { 02189 HASH->DIN = *(uint32_t *)inputaddr; 02190 inputaddr += 4U; 02191 } 02192 /* If this is the start of input data entering, an additional word 02193 must be entered to start up the HASH processing */ 02194 if (hhash->HashITCounter == 2U) 02195 { 02196 HASH->DIN = *(uint32_t *)inputaddr; 02197 if (hhash->HashInCount >= 68U) 02198 { 02199 /* There are still data waiting to be entered in the Peripheral. 02200 Decrement buffer counter and set pointer to the proper 02201 memory location for the next data entering round. */ 02202 hhash->HashInCount -= 68U; 02203 hhash->pHashInBuffPtr += 68U; 02204 } 02205 else 02206 { 02207 /* All the input buffer has been fed to the HW. */ 02208 hhash->HashInCount = 0U; 02209 } 02210 } 02211 else 02212 { 02213 /* 64 bytes have been entered and there are still some remaining: 02214 Decrement buffer counter and set pointer to the proper 02215 memory location for the next data entering round.*/ 02216 hhash->HashInCount -= 64U; 02217 hhash->pHashInBuffPtr += 64U; 02218 } 02219 } 02220 else 02221 { 02222 /* 64 or less bytes remain to be entered. This is the last 02223 data entering round. */ 02224 02225 /* Get the buffer address */ 02226 inputaddr = (uint32_t)hhash->pHashInBuffPtr; 02227 /* Get the buffer counter */ 02228 inputcounter = hhash->HashInCount; 02229 /* Disable Interrupts */ 02230 __HAL_HASH_DISABLE_IT(HASH_IT_DINI); 02231 02232 /* Write the Input block in the Data IN register */ 02233 for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++) 02234 { 02235 HASH->DIN = *(uint32_t *)inputaddr; 02236 inputaddr += 4U; 02237 } 02238 02239 if (hhash->Accumulation == 1U) 02240 { 02241 /* Field accumulation is set, API only feeds data to the Peripheral and under interruption. 02242 The digest computation will be started when the last buffer data are entered. */ 02243 02244 /* Reset multi buffers accumulation flag */ 02245 hhash->Accumulation = 0U; 02246 /* Change the HASH state */ 02247 hhash->State = HAL_HASH_STATE_READY; 02248 /* Call Input data transfer complete call back */ 02249 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) 02250 hhash->InCpltCallback(hhash); 02251 #else 02252 HAL_HASH_InCpltCallback(hhash); 02253 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ 02254 } 02255 else 02256 { 02257 /* Start the Digest calculation */ 02258 __HAL_HASH_START_DIGEST(); 02259 /* Return indication that digest calculation has started: 02260 this return value triggers the call to Input data transfer 02261 complete call back as well as the proper transition from 02262 one step to another in HMAC mode. */ 02263 ret = HASH_DIGEST_CALCULATION_STARTED; 02264 } 02265 /* Reset buffer counter */ 02266 hhash->HashInCount = 0; 02267 } 02268 02269 /* Return whether or digest calculation has started */ 02270 return ret; 02271 } 02272 02273 /** 02274 * @brief HMAC processing in polling mode. 02275 * @param hhash HASH handle. 02276 * @param Timeout Timeout value. 02277 * @retval HAL status 02278 */ 02279 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout) 02280 { 02281 /* Ensure first that Phase is correct */ 02282 if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2) 02283 && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3)) 02284 { 02285 /* Change the HASH state */ 02286 hhash->State = HAL_HASH_STATE_READY; 02287 02288 /* Process Unlock */ 02289 __HAL_UNLOCK(hhash); 02290 02291 /* Return function status */ 02292 return HAL_ERROR; 02293 } 02294 02295 /* HMAC Step 1 processing */ 02296 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) 02297 { 02298 /************************** STEP 1 ******************************************/ 02299 /* Configure the Number of valid bits in last word of the message */ 02300 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); 02301 02302 /* Write input buffer in Data register */ 02303 hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount); 02304 if (hhash->Status != HAL_OK) 02305 { 02306 return hhash->Status; 02307 } 02308 02309 /* Check whether or not key entering process has been suspended */ 02310 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 02311 { 02312 /* Process Unlocked */ 02313 __HAL_UNLOCK(hhash); 02314 02315 /* Stop right there and return function status */ 02316 return HAL_OK; 02317 } 02318 02319 /* No processing suspension at this point: set DCAL bit. */ 02320 __HAL_HASH_START_DIGEST(); 02321 02322 /* Wait for BUSY flag to be cleared */ 02323 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK) 02324 { 02325 return HAL_TIMEOUT; 02326 } 02327 02328 /* Move from Step 1 to Step 2 */ 02329 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; 02330 02331 } 02332 02333 /* HMAC Step 2 processing. 02334 After phase check, HMAC_Processing() may 02335 - directly start up from this point in resumption case 02336 if the same Step 2 processing was suspended previously 02337 - or fall through from the Step 1 processing carried out hereabove */ 02338 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) 02339 { 02340 /************************** STEP 2 ******************************************/ 02341 /* Configure the Number of valid bits in last word of the message */ 02342 __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); 02343 02344 /* Write input buffer in Data register */ 02345 hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount); 02346 if (hhash->Status != HAL_OK) 02347 { 02348 return hhash->Status; 02349 } 02350 02351 /* Check whether or not data entering process has been suspended */ 02352 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 02353 { 02354 /* Process Unlocked */ 02355 __HAL_UNLOCK(hhash); 02356 02357 /* Stop right there and return function status */ 02358 return HAL_OK; 02359 } 02360 02361 /* No processing suspension at this point: set DCAL bit. */ 02362 __HAL_HASH_START_DIGEST(); 02363 02364 /* Wait for BUSY flag to be cleared */ 02365 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK) 02366 { 02367 return HAL_TIMEOUT; 02368 } 02369 02370 /* Move from Step 2 to Step 3 */ 02371 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; 02372 /* In case Step 1 phase was suspended then resumed, 02373 set again Key input buffers and size before moving to 02374 next step */ 02375 hhash->pHashKeyBuffPtr = hhash->Init.pKey; 02376 hhash->HashKeyCount = hhash->Init.KeySize; 02377 } 02378 02379 02380 /* HMAC Step 3 processing. 02381 After phase check, HMAC_Processing() may 02382 - directly start up from this point in resumption case 02383 if the same Step 3 processing was suspended previously 02384 - or fall through from the Step 2 processing carried out hereabove */ 02385 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3) 02386 { 02387 /************************** STEP 3 ******************************************/ 02388 /* Configure the Number of valid bits in last word of the message */ 02389 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); 02390 02391 /* Write input buffer in Data register */ 02392 hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount); 02393 if (hhash->Status != HAL_OK) 02394 { 02395 return hhash->Status; 02396 } 02397 02398 /* Check whether or not key entering process has been suspended */ 02399 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 02400 { 02401 /* Process Unlocked */ 02402 __HAL_UNLOCK(hhash); 02403 02404 /* Stop right there and return function status */ 02405 return HAL_OK; 02406 } 02407 02408 /* No processing suspension at this point: start the Digest calculation. */ 02409 __HAL_HASH_START_DIGEST(); 02410 02411 /* Wait for DCIS flag to be set */ 02412 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) 02413 { 02414 return HAL_TIMEOUT; 02415 } 02416 02417 /* Read the message digest */ 02418 HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH()); 02419 02420 /* Reset HASH state machine */ 02421 hhash->Phase = HAL_HASH_PHASE_READY; 02422 } 02423 02424 /* Change the HASH state */ 02425 hhash->State = HAL_HASH_STATE_READY; 02426 02427 /* Process Unlock */ 02428 __HAL_UNLOCK(hhash); 02429 02430 /* Return function status */ 02431 return HAL_OK; 02432 } 02433 02434 02435 /** 02436 * @brief Initialize the HASH peripheral, next process pInBuffer then 02437 * read the computed digest. 02438 * @note Digest is available in pOutBuffer. 02439 * @param hhash HASH handle. 02440 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 02441 * @param Size length of the input buffer in bytes. 02442 * @param pOutBuffer pointer to the computed digest. 02443 * @param Timeout Timeout value. 02444 * @param Algorithm HASH algorithm. 02445 * @retval HAL status 02446 */ 02447 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 02448 uint32_t Timeout, uint32_t Algorithm) 02449 { 02450 uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */ 02451 uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */ 02452 HAL_HASH_StateTypeDef State_tmp = hhash->State; 02453 02454 02455 /* Initiate HASH processing in case of start or resumption */ 02456 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 02457 { 02458 /* Check input parameters */ 02459 if ((pInBuffer == NULL) || (pOutBuffer == NULL)) 02460 { 02461 hhash->State = HAL_HASH_STATE_READY; 02462 return HAL_ERROR; 02463 } 02464 02465 /* Process Locked */ 02466 __HAL_LOCK(hhash); 02467 02468 /* Check if initialization phase has not been already performed */ 02469 if (hhash->Phase == HAL_HASH_PHASE_READY) 02470 { 02471 /* Change the HASH state */ 02472 hhash->State = HAL_HASH_STATE_BUSY; 02473 02474 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 02475 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 02476 02477 /* Configure the number of valid bits in last word of the message */ 02478 __HAL_HASH_SET_NBVALIDBITS(Size); 02479 02480 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as 02481 input parameters of HASH_WriteData() */ 02482 pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */ 02483 Size_tmp = Size; /* Size_tmp contains the input data size in bytes */ 02484 02485 /* Set the phase */ 02486 hhash->Phase = HAL_HASH_PHASE_PROCESS; 02487 } 02488 else if (hhash->Phase == HAL_HASH_PHASE_PROCESS) 02489 { 02490 /* if the Peripheral has already been initialized, two cases are possible */ 02491 02492 /* Process resumption time ... */ 02493 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 02494 { 02495 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set 02496 to the API input parameters but to those saved beforehand by HASH_WriteData() 02497 when the processing was suspended */ 02498 pInBuffer_tmp = hhash->pHashInBuffPtr; 02499 Size_tmp = hhash->HashInCount; 02500 } 02501 /* ... or multi-buffer HASH processing end */ 02502 else 02503 { 02504 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as 02505 input parameters of HASH_WriteData() */ 02506 pInBuffer_tmp = pInBuffer; 02507 Size_tmp = Size; 02508 /* Configure the number of valid bits in last word of the message */ 02509 __HAL_HASH_SET_NBVALIDBITS(Size); 02510 } 02511 /* Change the HASH state */ 02512 hhash->State = HAL_HASH_STATE_BUSY; 02513 } 02514 else 02515 { 02516 /* Phase error */ 02517 hhash->State = HAL_HASH_STATE_READY; 02518 02519 /* Process Unlocked */ 02520 __HAL_UNLOCK(hhash); 02521 02522 /* Return function status */ 02523 return HAL_ERROR; 02524 } 02525 02526 02527 /* Write input buffer in Data register */ 02528 hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp); 02529 if (hhash->Status != HAL_OK) 02530 { 02531 return hhash->Status; 02532 } 02533 02534 /* If the process has not been suspended, carry on to digest calculation */ 02535 if (hhash->State != HAL_HASH_STATE_SUSPENDED) 02536 { 02537 /* Start the Digest calculation */ 02538 __HAL_HASH_START_DIGEST(); 02539 02540 /* Wait for DCIS flag to be set */ 02541 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) 02542 { 02543 return HAL_TIMEOUT; 02544 } 02545 02546 /* Read the message digest */ 02547 HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH()); 02548 02549 /* Change the HASH state */ 02550 hhash->State = HAL_HASH_STATE_READY; 02551 02552 /* Reset HASH state machine */ 02553 hhash->Phase = HAL_HASH_PHASE_READY; 02554 02555 } 02556 02557 /* Process Unlocked */ 02558 __HAL_UNLOCK(hhash); 02559 02560 /* Return function status */ 02561 return HAL_OK; 02562 02563 } 02564 else 02565 { 02566 return HAL_BUSY; 02567 } 02568 } 02569 02570 02571 /** 02572 * @brief If not already done, initialize the HASH peripheral then 02573 * processes pInBuffer. 02574 * @note Field hhash->Phase of HASH handle is tested to check whether or not 02575 * the Peripheral has already been initialized. 02576 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 02577 * HASH digest computation is corrupted. 02578 * @param hhash HASH handle. 02579 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 02580 * @param Size length of the input buffer in bytes, must be a multiple of 4. 02581 * @param Algorithm HASH algorithm. 02582 * @retval HAL status 02583 */ 02584 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) 02585 { 02586 uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */ 02587 uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */ 02588 HAL_HASH_StateTypeDef State_tmp = hhash->State; 02589 02590 /* Make sure the input buffer size (in bytes) is a multiple of 4 */ 02591 if ((Size % 4U) != 0U) 02592 { 02593 return HAL_ERROR; 02594 } 02595 02596 /* Initiate HASH processing in case of start or resumption */ 02597 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 02598 { 02599 /* Check input parameters */ 02600 if ((pInBuffer == NULL) || (Size == 0U)) 02601 { 02602 hhash->State = HAL_HASH_STATE_READY; 02603 return HAL_ERROR; 02604 } 02605 02606 /* Process Locked */ 02607 __HAL_LOCK(hhash); 02608 02609 /* If resuming the HASH processing */ 02610 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 02611 { 02612 /* Change the HASH state */ 02613 hhash->State = HAL_HASH_STATE_BUSY; 02614 02615 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set 02616 to the API input parameters but to those saved beforehand by HASH_WriteData() 02617 when the processing was suspended */ 02618 pInBuffer_tmp = hhash->pHashInBuffPtr; /* pInBuffer_tmp is set to the input data address */ 02619 Size_tmp = hhash->HashInCount; /* Size_tmp contains the input data size in bytes */ 02620 02621 } 02622 else 02623 { 02624 /* Change the HASH state */ 02625 hhash->State = HAL_HASH_STATE_BUSY; 02626 02627 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as 02628 input parameters of HASH_WriteData() */ 02629 pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */ 02630 Size_tmp = Size; /* Size_tmp contains the input data size in bytes */ 02631 02632 /* Check if initialization phase has already be performed */ 02633 if (hhash->Phase == HAL_HASH_PHASE_READY) 02634 { 02635 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 02636 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 02637 } 02638 02639 /* Set the phase */ 02640 hhash->Phase = HAL_HASH_PHASE_PROCESS; 02641 02642 } 02643 02644 /* Write input buffer in Data register */ 02645 hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp); 02646 if (hhash->Status != HAL_OK) 02647 { 02648 return hhash->Status; 02649 } 02650 02651 /* If the process has not been suspended, move the state to Ready */ 02652 if (hhash->State != HAL_HASH_STATE_SUSPENDED) 02653 { 02654 /* Change the HASH state */ 02655 hhash->State = HAL_HASH_STATE_READY; 02656 } 02657 02658 /* Process Unlocked */ 02659 __HAL_UNLOCK(hhash); 02660 02661 /* Return function status */ 02662 return HAL_OK; 02663 02664 } 02665 else 02666 { 02667 return HAL_BUSY; 02668 } 02669 02670 02671 } 02672 02673 02674 /** 02675 * @brief If not already done, initialize the HASH peripheral then 02676 * processes pInBuffer in interruption mode. 02677 * @note Field hhash->Phase of HASH handle is tested to check whether or not 02678 * the Peripheral has already been initialized. 02679 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the 02680 * HASH digest computation is corrupted. 02681 * @param hhash HASH handle. 02682 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 02683 * @param Size length of the input buffer in bytes, must be a multiple of 4. 02684 * @param Algorithm HASH algorithm. 02685 * @retval HAL status 02686 */ 02687 HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) 02688 { 02689 HAL_HASH_StateTypeDef State_tmp = hhash->State; 02690 __IO uint32_t inputaddr = (uint32_t) pInBuffer; 02691 uint32_t SizeVar = Size; 02692 02693 /* Make sure the input buffer size (in bytes) is a multiple of 4 */ 02694 if ((Size % 4U) != 0U) 02695 { 02696 return HAL_ERROR; 02697 } 02698 02699 /* Initiate HASH processing in case of start or resumption */ 02700 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 02701 { 02702 /* Check input parameters */ 02703 if ((pInBuffer == NULL) || (Size == 0U)) 02704 { 02705 hhash->State = HAL_HASH_STATE_READY; 02706 return HAL_ERROR; 02707 } 02708 02709 /* Process Locked */ 02710 __HAL_LOCK(hhash); 02711 02712 /* If resuming the HASH processing */ 02713 if (hhash->State == HAL_HASH_STATE_SUSPENDED) 02714 { 02715 /* Change the HASH state */ 02716 hhash->State = HAL_HASH_STATE_BUSY; 02717 } 02718 else 02719 { 02720 /* Change the HASH state */ 02721 hhash->State = HAL_HASH_STATE_BUSY; 02722 02723 /* Check if initialization phase has already be performed */ 02724 if (hhash->Phase == HAL_HASH_PHASE_READY) 02725 { 02726 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 02727 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 02728 hhash->HashITCounter = 1; 02729 } 02730 else 02731 { 02732 hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */ 02733 } 02734 02735 /* Set the phase */ 02736 hhash->Phase = HAL_HASH_PHASE_PROCESS; 02737 02738 /* If DINIS is equal to 0 (for example if an incomplete block has been previously 02739 fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set. 02740 Therefore, first words are manually entered until DINIS raises, or until there 02741 is not more data to enter. */ 02742 while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U)) 02743 { 02744 02745 /* Write input data 4 bytes at a time */ 02746 HASH->DIN = *(uint32_t *)inputaddr; 02747 inputaddr += 4U; 02748 SizeVar -= 4U; 02749 } 02750 02751 /* If DINIS is still not set or if all the data have been fed, stop here */ 02752 if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U)) 02753 { 02754 /* Change the HASH state */ 02755 hhash->State = HAL_HASH_STATE_READY; 02756 02757 /* Process Unlock */ 02758 __HAL_UNLOCK(hhash); 02759 02760 /* Return function status */ 02761 return HAL_OK; 02762 } 02763 02764 /* otherwise, carry on in interrupt-mode */ 02765 hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data 02766 to be fed to the Peripheral */ 02767 hhash->pHashInBuffPtr = (uint8_t *)inputaddr; /* Points at data which will be fed to the Peripheral at 02768 the next interruption */ 02769 /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain 02770 the information describing where the HASH process is stopped. 02771 These variables are used later on to resume the HASH processing at the 02772 correct location. */ 02773 02774 } 02775 02776 /* Set multi buffers accumulation flag */ 02777 hhash->Accumulation = 1U; 02778 02779 /* Process Unlock */ 02780 __HAL_UNLOCK(hhash); 02781 02782 /* Enable Data Input interrupt */ 02783 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); 02784 02785 /* Return function status */ 02786 return HAL_OK; 02787 02788 } 02789 else 02790 { 02791 return HAL_BUSY; 02792 } 02793 02794 } 02795 02796 02797 02798 /** 02799 * @brief Initialize the HASH peripheral, next process pInBuffer then 02800 * read the computed digest in interruption mode. 02801 * @note Digest is available in pOutBuffer. 02802 * @param hhash HASH handle. 02803 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 02804 * @param Size length of the input buffer in bytes. 02805 * @param pOutBuffer pointer to the computed digest. 02806 * @param Algorithm HASH algorithm. 02807 * @retval HAL status 02808 */ 02809 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 02810 uint32_t Algorithm) 02811 { 02812 HAL_HASH_StateTypeDef State_tmp = hhash->State; 02813 __IO uint32_t inputaddr = (uint32_t) pInBuffer; 02814 uint32_t polling_step = 0U; 02815 uint32_t initialization_skipped = 0U; 02816 uint32_t SizeVar = Size; 02817 02818 /* If State is ready or suspended, start or resume IT-based HASH processing */ 02819 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 02820 { 02821 /* Check input parameters */ 02822 if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL)) 02823 { 02824 hhash->State = HAL_HASH_STATE_READY; 02825 return HAL_ERROR; 02826 } 02827 02828 /* Process Locked */ 02829 __HAL_LOCK(hhash); 02830 02831 /* Change the HASH state */ 02832 hhash->State = HAL_HASH_STATE_BUSY; 02833 02834 /* Initialize IT counter */ 02835 hhash->HashITCounter = 1; 02836 02837 /* Check if initialization phase has already be performed */ 02838 if (hhash->Phase == HAL_HASH_PHASE_READY) 02839 { 02840 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 02841 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 02842 02843 /* Configure the number of valid bits in last word of the message */ 02844 __HAL_HASH_SET_NBVALIDBITS(SizeVar); 02845 02846 02847 hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data 02848 to be fed to the Peripheral */ 02849 hhash->pHashInBuffPtr = pInBuffer; /* Points at data which will be fed to the Peripheral at 02850 the next interruption */ 02851 /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain 02852 the information describing where the HASH process is stopped. 02853 These variables are used later on to resume the HASH processing at the 02854 correct location. */ 02855 02856 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ 02857 } 02858 else 02859 { 02860 initialization_skipped = 1; /* info user later on in case of multi-buffer */ 02861 } 02862 02863 /* Set the phase */ 02864 hhash->Phase = HAL_HASH_PHASE_PROCESS; 02865 02866 /* If DINIS is equal to 0 (for example if an incomplete block has been previously 02867 fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set. 02868 Therefore, first words are manually entered until DINIS raises. */ 02869 while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U)) 02870 { 02871 polling_step = 1U; /* note that some words are entered before enabling the interrupt */ 02872 02873 /* Write input data 4 bytes at a time */ 02874 HASH->DIN = *(uint32_t *)inputaddr; 02875 inputaddr += 4U; 02876 SizeVar -= 4U; 02877 } 02878 02879 if (polling_step == 1U) 02880 { 02881 if (SizeVar == 0U) 02882 { 02883 /* If all the data have been entered at this point, it only remains to 02884 read the digest */ 02885 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ 02886 02887 /* Start the Digest calculation */ 02888 __HAL_HASH_START_DIGEST(); 02889 /* Process Unlock */ 02890 __HAL_UNLOCK(hhash); 02891 02892 /* Enable Interrupts */ 02893 __HAL_HASH_ENABLE_IT(HASH_IT_DCI); 02894 02895 /* Return function status */ 02896 return HAL_OK; 02897 } 02898 else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) 02899 { 02900 /* It remains data to enter and the Peripheral is ready to trigger DINIE, 02901 carry on as usual. 02902 Update HashInCount and pHashInBuffPtr accordingly. */ 02903 hhash->HashInCount = SizeVar; 02904 hhash->pHashInBuffPtr = (uint8_t *)inputaddr; 02905 /* Update the configuration of the number of valid bits in last word of the message */ 02906 __HAL_HASH_SET_NBVALIDBITS(SizeVar); 02907 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ 02908 if (initialization_skipped == 1U) 02909 { 02910 hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */ 02911 } 02912 } 02913 else 02914 { 02915 /* DINIS is not set but it remains a few data to enter (not enough for a full word). 02916 Manually enter the last bytes before enabling DCIE. */ 02917 __HAL_HASH_SET_NBVALIDBITS(SizeVar); 02918 HASH->DIN = *(uint32_t *)inputaddr; 02919 02920 /* Start the Digest calculation */ 02921 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ 02922 __HAL_HASH_START_DIGEST(); 02923 /* Process Unlock */ 02924 __HAL_UNLOCK(hhash); 02925 02926 /* Enable Interrupts */ 02927 __HAL_HASH_ENABLE_IT(HASH_IT_DCI); 02928 02929 /* Return function status */ 02930 return HAL_OK; 02931 } 02932 } /* if (polling_step == 1) */ 02933 02934 02935 /* Process Unlock */ 02936 __HAL_UNLOCK(hhash); 02937 02938 /* Enable Interrupts */ 02939 __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 02940 02941 /* Return function status */ 02942 return HAL_OK; 02943 } 02944 else 02945 { 02946 return HAL_BUSY; 02947 } 02948 02949 } 02950 02951 02952 /** 02953 * @brief Initialize the HASH peripheral then initiate a DMA transfer 02954 * to feed the input buffer to the Peripheral. 02955 * @note If MDMAT bit is set before calling this function (multi-buffer 02956 * HASH processing case), the input buffer size (in bytes) must be 02957 * a multiple of 4 otherwise, the HASH digest computation is corrupted. 02958 * For the processing of the last buffer of the thread, MDMAT bit must 02959 * be reset and the buffer length (in bytes) doesn't have to be a 02960 * multiple of 4. 02961 * @param hhash HASH handle. 02962 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 02963 * @param Size length of the input buffer in bytes. 02964 * @param Algorithm HASH algorithm. 02965 * @retval HAL status 02966 */ 02967 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) 02968 { 02969 uint32_t inputaddr; 02970 uint32_t inputSize; 02971 HAL_StatusTypeDef status ; 02972 HAL_HASH_StateTypeDef State_tmp = hhash->State; 02973 02974 02975 /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set 02976 (case of multi-buffer HASH processing) */ 02977 assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size)); 02978 02979 /* If State is ready or suspended, start or resume polling-based HASH processing */ 02980 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 02981 { 02982 /* Check input parameters */ 02983 if ((pInBuffer == NULL) || (Size == 0U) || 02984 /* Check phase coherency. Phase must be 02985 either READY (fresh start) 02986 or PROCESS (multi-buffer HASH management) */ 02987 ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash))))) 02988 { 02989 hhash->State = HAL_HASH_STATE_READY; 02990 return HAL_ERROR; 02991 } 02992 02993 02994 /* Process Locked */ 02995 __HAL_LOCK(hhash); 02996 02997 /* If not a resumption case */ 02998 if (hhash->State == HAL_HASH_STATE_READY) 02999 { 03000 /* Change the HASH state */ 03001 hhash->State = HAL_HASH_STATE_BUSY; 03002 03003 /* Check if initialization phase has already been performed. 03004 If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the 03005 API is processing a new input data message in case of multi-buffer HASH 03006 computation. */ 03007 if (hhash->Phase == HAL_HASH_PHASE_READY) 03008 { 03009 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ 03010 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); 03011 03012 /* Set the phase */ 03013 hhash->Phase = HAL_HASH_PHASE_PROCESS; 03014 } 03015 03016 /* Configure the Number of valid bits in last word of the message */ 03017 __HAL_HASH_SET_NBVALIDBITS(Size); 03018 03019 inputaddr = (uint32_t)pInBuffer; /* DMA transfer start address */ 03020 inputSize = Size; /* DMA transfer size (in bytes) */ 03021 03022 /* In case of suspension request, save the starting parameters */ 03023 hhash->pHashInBuffPtr = pInBuffer; /* DMA transfer start address */ 03024 hhash->HashInCount = Size; /* DMA transfer size (in bytes) */ 03025 03026 } 03027 /* If resumption case */ 03028 else 03029 { 03030 /* Change the HASH state */ 03031 hhash->State = HAL_HASH_STATE_BUSY; 03032 03033 /* Resumption case, inputaddr and inputSize are not set to the API input parameters 03034 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the 03035 processing was suspended */ 03036 inputaddr = (uint32_t)hhash->pHashInBuffPtr; /* DMA transfer start address */ 03037 inputSize = hhash->HashInCount; /* DMA transfer size (in bytes) */ 03038 03039 } 03040 03041 /* Set the HASH DMA transfer complete callback */ 03042 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; 03043 /* Set the DMA error callback */ 03044 hhash->hdmain->XferErrorCallback = HASH_DMAError; 03045 03046 /* Store number of words already pushed to manage proper DMA processing suspension */ 03047 hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED(); 03048 03049 /* Enable the DMA In DMA stream */ 03050 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \ 03051 (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \ 03052 (inputSize / 4U))); 03053 03054 /* Enable DMA requests */ 03055 SET_BIT(HASH->CR, HASH_CR_DMAE); 03056 03057 /* Process Unlock */ 03058 __HAL_UNLOCK(hhash); 03059 03060 /* Return function status */ 03061 if (status != HAL_OK) 03062 { 03063 /* Update HASH state machine to error */ 03064 hhash->State = HAL_HASH_STATE_ERROR; 03065 } 03066 03067 return status; 03068 } 03069 else 03070 { 03071 return HAL_BUSY; 03072 } 03073 } 03074 03075 /** 03076 * @brief Return the computed digest. 03077 * @note The API waits for DCIS to be set then reads the computed digest. 03078 * @param hhash HASH handle. 03079 * @param pOutBuffer pointer to the computed digest. 03080 * @param Timeout Timeout value. 03081 * @retval HAL status 03082 */ 03083 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) 03084 { 03085 03086 if (hhash->State == HAL_HASH_STATE_READY) 03087 { 03088 /* Check parameter */ 03089 if (pOutBuffer == NULL) 03090 { 03091 return HAL_ERROR; 03092 } 03093 03094 /* Process Locked */ 03095 __HAL_LOCK(hhash); 03096 03097 /* Change the HASH state to busy */ 03098 hhash->State = HAL_HASH_STATE_BUSY; 03099 03100 /* Wait for DCIS flag to be set */ 03101 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) 03102 { 03103 return HAL_TIMEOUT; 03104 } 03105 03106 /* Read the message digest */ 03107 HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH()); 03108 03109 /* Change the HASH state to ready */ 03110 hhash->State = HAL_HASH_STATE_READY; 03111 03112 /* Reset HASH state machine */ 03113 hhash->Phase = HAL_HASH_PHASE_READY; 03114 03115 /* Process UnLock */ 03116 __HAL_UNLOCK(hhash); 03117 03118 /* Return function status */ 03119 return HAL_OK; 03120 03121 } 03122 else 03123 { 03124 return HAL_BUSY; 03125 } 03126 03127 } 03128 03129 03130 /** 03131 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then 03132 * read the computed digest. 03133 * @note Digest is available in pOutBuffer. 03134 * @note Same key is used for the inner and the outer hash functions; pointer to key and 03135 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 03136 * @param hhash HASH handle. 03137 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 03138 * @param Size length of the input buffer in bytes. 03139 * @param pOutBuffer pointer to the computed digest. 03140 * @param Timeout Timeout value. 03141 * @param Algorithm HASH algorithm. 03142 * @retval HAL status 03143 */ 03144 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 03145 uint32_t Timeout, uint32_t Algorithm) 03146 { 03147 HAL_HASH_StateTypeDef State_tmp = hhash->State; 03148 03149 /* If State is ready or suspended, start or resume polling-based HASH processing */ 03150 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 03151 { 03152 /* Check input parameters */ 03153 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) 03154 || (pOutBuffer == NULL)) 03155 { 03156 hhash->State = HAL_HASH_STATE_READY; 03157 return HAL_ERROR; 03158 } 03159 03160 /* Process Locked */ 03161 __HAL_LOCK(hhash); 03162 03163 /* Change the HASH state */ 03164 hhash->State = HAL_HASH_STATE_BUSY; 03165 03166 /* Check if initialization phase has already be performed */ 03167 if (hhash->Phase == HAL_HASH_PHASE_READY) 03168 { 03169 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */ 03170 if (hhash->Init.KeySize > 64U) 03171 { 03172 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 03173 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); 03174 } 03175 else 03176 { 03177 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 03178 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); 03179 } 03180 /* Set the phase to Step 1 */ 03181 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; 03182 /* Resort to hhash internal fields to feed the Peripheral. 03183 Parameters will be updated in case of suspension to contain the proper 03184 information at resumption time. */ 03185 hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */ 03186 hhash->pHashInBuffPtr = pInBuffer; /* Input data address, HMAC_Processing input 03187 parameter for Step 2 */ 03188 hhash->HashInCount = Size; /* Input data size, HMAC_Processing input 03189 parameter for Step 2 */ 03190 hhash->HashBuffSize = Size; /* Store the input buffer size for the whole HMAC process*/ 03191 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address, HMAC_Processing input parameter for Step 03192 1 and Step 3 */ 03193 hhash->HashKeyCount = hhash->Init.KeySize; /* Key size, HMAC_Processing input parameter for Step 1 03194 and Step 3 */ 03195 } 03196 03197 /* Carry out HMAC processing */ 03198 return HMAC_Processing(hhash, Timeout); 03199 03200 } 03201 else 03202 { 03203 return HAL_BUSY; 03204 } 03205 } 03206 03207 03208 03209 /** 03210 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then 03211 * read the computed digest in interruption mode. 03212 * @note Digest is available in pOutBuffer. 03213 * @note Same key is used for the inner and the outer hash functions; pointer to key and 03214 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 03215 * @param hhash HASH handle. 03216 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 03217 * @param Size length of the input buffer in bytes. 03218 * @param pOutBuffer pointer to the computed digest. 03219 * @param Algorithm HASH algorithm. 03220 * @retval HAL status 03221 */ 03222 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, 03223 uint32_t Algorithm) 03224 { 03225 HAL_HASH_StateTypeDef State_tmp = hhash->State; 03226 03227 /* If State is ready or suspended, start or resume IT-based HASH processing */ 03228 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 03229 { 03230 /* Check input parameters */ 03231 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) 03232 || (pOutBuffer == NULL)) 03233 { 03234 hhash->State = HAL_HASH_STATE_READY; 03235 return HAL_ERROR; 03236 } 03237 03238 /* Process Locked */ 03239 __HAL_LOCK(hhash); 03240 03241 /* Change the HASH state */ 03242 hhash->State = HAL_HASH_STATE_BUSY; 03243 03244 /* Initialize IT counter */ 03245 hhash->HashITCounter = 1; 03246 03247 /* Check if initialization phase has already be performed */ 03248 if (hhash->Phase == HAL_HASH_PHASE_READY) 03249 { 03250 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */ 03251 if (hhash->Init.KeySize > 64U) 03252 { 03253 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 03254 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); 03255 } 03256 else 03257 { 03258 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 03259 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); 03260 } 03261 03262 /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount 03263 to feed the Peripheral whatever the HMAC step. 03264 Lines below are set to start HMAC Step 1 processing where key is entered first. */ 03265 hhash->HashInCount = hhash->Init.KeySize; /* Key size */ 03266 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* Key address */ 03267 03268 /* Store input and output parameters in handle fields to manage steps transition 03269 or possible HMAC suspension/resumption */ 03270 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */ 03271 hhash->pHashMsgBuffPtr = pInBuffer; /* Input message address */ 03272 hhash->HashBuffSize = Size; /* Input message size (in bytes) */ 03273 hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */ 03274 03275 /* Configure the number of valid bits in last word of the key */ 03276 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); 03277 03278 /* Set the phase to Step 1 */ 03279 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; 03280 } 03281 else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)) 03282 { 03283 /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */ 03284 03285 } 03286 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) 03287 { 03288 /* Restart IT-based HASH processing after Step 2 suspension */ 03289 03290 } 03291 else 03292 { 03293 /* Error report as phase incorrect */ 03294 /* Process Unlock */ 03295 __HAL_UNLOCK(hhash); 03296 hhash->State = HAL_HASH_STATE_READY; 03297 return HAL_ERROR; 03298 } 03299 03300 /* Process Unlock */ 03301 __HAL_UNLOCK(hhash); 03302 03303 /* Enable Interrupts */ 03304 __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI); 03305 03306 /* Return function status */ 03307 return HAL_OK; 03308 } 03309 else 03310 { 03311 return HAL_BUSY; 03312 } 03313 03314 } 03315 03316 03317 03318 /** 03319 * @brief Initialize the HASH peripheral in HMAC mode then initiate the required 03320 * DMA transfers to feed the key and the input buffer to the Peripheral. 03321 * @note Same key is used for the inner and the outer hash functions; pointer to key and 03322 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. 03323 * @note In case of multi-buffer HMAC processing, the input buffer size (in bytes) must 03324 * be a multiple of 4 otherwise, the HASH digest computation is corrupted. 03325 * Only the length of the last buffer of the thread doesn't have to be a 03326 * multiple of 4. 03327 * @param hhash HASH handle. 03328 * @param pInBuffer pointer to the input buffer (buffer to be hashed). 03329 * @param Size length of the input buffer in bytes. 03330 * @param Algorithm HASH algorithm. 03331 * @retval HAL status 03332 */ 03333 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) 03334 { 03335 uint32_t inputaddr; 03336 uint32_t inputSize; 03337 HAL_StatusTypeDef status ; 03338 HAL_HASH_StateTypeDef State_tmp = hhash->State; 03339 /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation 03340 is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */ 03341 assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size)); 03342 /* If State is ready or suspended, start or resume DMA-based HASH processing */ 03343 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) 03344 { 03345 /* Check input parameters */ 03346 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || 03347 /* Check phase coherency. Phase must be 03348 either READY (fresh start) 03349 or one of HMAC PROCESS steps (multi-buffer HASH management) */ 03350 ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash))))) 03351 { 03352 hhash->State = HAL_HASH_STATE_READY; 03353 return HAL_ERROR; 03354 } 03355 03356 03357 /* Process Locked */ 03358 __HAL_LOCK(hhash); 03359 03360 /* If not a case of resumption after suspension */ 03361 if (hhash->State == HAL_HASH_STATE_READY) 03362 { 03363 /* Check whether or not initialization phase has already be performed */ 03364 if (hhash->Phase == HAL_HASH_PHASE_READY) 03365 { 03366 /* Change the HASH state */ 03367 hhash->State = HAL_HASH_STATE_BUSY; 03368 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits. 03369 At the same time, ensure MDMAT bit is cleared. */ 03370 if (hhash->Init.KeySize > 64U) 03371 { 03372 MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 03373 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); 03374 } 03375 else 03376 { 03377 MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, 03378 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); 03379 } 03380 /* Store input aparameters in handle fields to manage steps transition 03381 or possible HMAC suspension/resumption */ 03382 hhash->HashInCount = hhash->Init.KeySize; /* Initial size for first DMA transfer (key size) */ 03383 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */ 03384 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */ 03385 hhash->pHashMsgBuffPtr = pInBuffer; /* Input data address */ 03386 hhash->HashBuffSize = Size; /* input data size (in bytes) */ 03387 03388 /* Set DMA input parameters */ 03389 inputaddr = (uint32_t)(hhash->Init.pKey); /* Address passed to DMA (start by entering Key message) */ 03390 inputSize = hhash->Init.KeySize; /* Size for first DMA transfer (in bytes) */ 03391 03392 /* Configure the number of valid bits in last word of the key */ 03393 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); 03394 03395 /* Set the phase to Step 1 */ 03396 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; 03397 03398 } 03399 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) 03400 { 03401 /* Process a new input data message in case of multi-buffer HMAC processing 03402 (this is not a resumption case) */ 03403 03404 /* Change the HASH state */ 03405 hhash->State = HAL_HASH_STATE_BUSY; 03406 03407 /* Save input parameters to be able to manage possible suspension/resumption */ 03408 hhash->HashInCount = Size; /* Input message address */ 03409 hhash->pHashInBuffPtr = pInBuffer; /* Input message size in bytes */ 03410 03411 /* Set DMA input parameters */ 03412 inputaddr = (uint32_t)pInBuffer; /* Input message address */ 03413 inputSize = Size; /* Input message size in bytes */ 03414 03415 if (hhash->DigestCalculationDisable == RESET) 03416 { 03417 /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */ 03418 __HAL_HASH_RESET_MDMAT(); 03419 __HAL_HASH_SET_NBVALIDBITS(inputSize); 03420 } 03421 } 03422 else 03423 { 03424 /* Phase not aligned with handle READY state */ 03425 __HAL_UNLOCK(hhash); 03426 /* Return function status */ 03427 return HAL_ERROR; 03428 } 03429 } 03430 else 03431 { 03432 /* Resumption case (phase may be Step 1, 2 or 3) */ 03433 03434 /* Change the HASH state */ 03435 hhash->State = HAL_HASH_STATE_BUSY; 03436 03437 /* Set DMA input parameters at resumption location; 03438 inputaddr and inputSize are not set to the API input parameters 03439 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the 03440 processing was suspended. */ 03441 inputaddr = (uint32_t)(hhash->pHashInBuffPtr); /* Input message address */ 03442 inputSize = hhash->HashInCount; /* Input message size in bytes */ 03443 } 03444 03445 03446 /* Set the HASH DMA transfer complete callback */ 03447 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; 03448 /* Set the DMA error callback */ 03449 hhash->hdmain->XferErrorCallback = HASH_DMAError; 03450 03451 /* Store number of words already pushed to manage proper DMA processing suspension */ 03452 hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED(); 03453 03454 /* Enable the DMA In DMA stream */ 03455 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \ 03456 (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \ 03457 : (inputSize / 4U))); 03458 03459 /* Enable DMA requests */ 03460 SET_BIT(HASH->CR, HASH_CR_DMAE); 03461 03462 /* Process Unlocked */ 03463 __HAL_UNLOCK(hhash); 03464 03465 /* Return function status */ 03466 if (status != HAL_OK) 03467 { 03468 /* Update HASH state machine to error */ 03469 hhash->State = HAL_HASH_STATE_ERROR; 03470 } 03471 03472 /* Return function status */ 03473 return status; 03474 } 03475 else 03476 { 03477 return HAL_BUSY; 03478 } 03479 } 03480 /** 03481 * @} 03482 */ 03483 03484 #endif /* HAL_HASH_MODULE_ENABLED */ 03485 03486 /** 03487 * @} 03488 */ 03489 #endif /* HASH*/ 03490 /** 03491 * @} 03492 */ 03493