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