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