1 /**
2   ******************************************************************************
3   * @file    stm32l4xx_hal_hash.c
4   * @author  MCD Application Team
5   * @brief   HASH HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the HASH peripheral:
8   *           + Initialization and de-initialization methods
9   *           + HASH or HMAC processing in polling mode
10   *           + HASH or HMAC processing in interrupt mode
11   *           + HASH or HMAC processing in DMA mode
12   *           + Peripheral State methods
13   *           + HASH or HMAC processing suspension/resumption
14   *
15   @verbatim
16  ===============================================================================
17                      ##### How to use this driver #####
18  ===============================================================================
19     [..]
20     The HASH HAL driver can be used as follows:
21 
22     (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit():
23         (##) Enable the HASH interface clock using __HASH_CLK_ENABLE()
24         (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT())
25             (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority()
26             (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ()
27             (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API
28         (##) When resorting to DMA-based APIs  (e.g. HAL_HASH_xxx_Start_DMA())
29             (+++) Enable the DMAx interface clock using
30                    __DMAx_CLK_ENABLE()
31             (+++) Configure and enable one DMA stream to manage data transfer from
32                 memory to peripheral (input stream). Managing data transfer from
33                 peripheral to memory can be performed only using CPU.
34             (+++) Associate the initialized DMA handle to the HASH DMA handle
35                 using  __HAL_LINKDMA()
36             (+++) Configure the priority and enable the NVIC for the transfer complete
37                 interrupt on the DMA Stream: use
38                  HAL_NVIC_SetPriority() and
39                  HAL_NVIC_EnableIRQ()
40 
41     (#)Initialize the HASH HAL using HAL_HASH_Init(). This function:
42         (##) resorts to HAL_HASH_MspInit() for low-level initialization,
43         (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit.
44 
45     (#)Three processing schemes are available:
46         (##) Polling mode: processing APIs are blocking functions
47              i.e. they process the data and wait till the digest computation is finished,
48              e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC
49         (##) Interrupt mode: processing APIs are not blocking functions
50                 i.e. they process the data under interrupt,
51                 e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC
52         (##) DMA mode: processing APIs are not blocking functions and the CPU is
53              not used for data transfer i.e. the data transfer is ensured by DMA,
54                 e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA()
55                 for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish()
56                 is then required to retrieve the digest.
57 
58     (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is
59        initialized and processes the buffer fed in input. When the input data have all been
60        fed to the IP, the digest computation can start.
61 
62     (#)Multi-buffer processing is possible in polling and DMA mode.
63         (##) In polling mode, only multi-buffer HASH processing is possible.
64              API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one.
65              User must resort to HAL_HASH_xxx_Start() to enter the last one and retrieve as
66              well the computed digest.
67 
68         (##) In DMA mode, multi-buffer HASH and HMAC processing are possible.
69               (+++) HASH processing: once initialization is done, MDMAT bit must be set thru __HAL_HASH_SET_MDMAT() macro.
70              From that point, each buffer can be fed to the IP thru HAL_HASH_xxx_Start_DMA() API.
71              Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT()
72              macro then wrap-up the HASH processing in feeding the last input buffer thru the
73              same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to
74              API HAL_HASH_xxx_Finish().
75              (+++) HMAC processing (requires to resort to extended functions):
76              after initialization, the key and the first input buffer are entered
77              in the IP with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
78              starts step 2.
79              The following buffers are next entered with the API  HAL_HMACEx_xxx_Step2_DMA(). At this
80              point, the HMAC processing is still carrying out step 2.
81              Then, step 2 for the last input buffer and step 3 are carried out by a single call
82              to HAL_HMACEx_xxx_Step2_3_DMA().
83 
84              The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish().
85 
86 
87     (#)Context swapping.
88         (##) Two APIs are available to suspend HASH or HMAC processing:
89              (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode),
90              (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA.
91 
92         (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows
93             to save in memory the IP context. This context can be restored afterwards
94             to resume the HASH processing thanks to HAL_HASH_ContextRestoring().
95 
96         (##) Once the HASH IP has been restored to the same configuration as that at suspension
97              time, processing can be restarted with the same API call (same API, same handle,
98              same parameters) as done before the suspension. Relevant parameters to restart at
99              the proper location are internally saved in the HASH handle.
100 
101     (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
102 
103      *** Callback registration ***
104      ===================================
105      [..]
106       (#) The compilation define  USE_HAL_HASH_REGISTER_CALLBACKS when set to 1
107           allows the user to configure dynamically the driver callbacks.
108           Use function @ref HAL_HASH_RegisterCallback() to register a user callback.
109 
110       (#) Function @ref HAL_HASH_RegisterCallback() allows to register following callbacks:
111             (+) InCpltCallback    : callback for input completion.
112             (+) DgstCpltCallback  : callback for digest computation completion.
113             (+) ErrorCallback     : callback for error.
114             (+) MspInitCallback   : HASH MspInit.
115             (+) MspDeInitCallback : HASH MspDeInit.
116           This function takes as parameters the HAL peripheral handle, the Callback ID
117           and a pointer to the user callback function.
118 
119       (#) Use function @ref HAL_HASH_UnRegisterCallback() to reset a callback to the default
120           weak (surcharged) function.
121           @ref HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle,
122           and the Callback ID.
123           This function allows to reset following callbacks:
124             (+) InCpltCallback    : callback for input completion.
125             (+) DgstCpltCallback  : callback for digest computation completion.
126             (+) ErrorCallback     : callback for error.
127             (+) MspInitCallback   : HASH MspInit.
128             (+) MspDeInitCallback : HASH MspDeInit.
129 
130       (#) By default, after the @ref HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET
131           all callbacks are reset to the corresponding legacy weak (surcharged) functions:
132           examples @ref HAL_HASH_InCpltCallback(), @ref HAL_HASH_DgstCpltCallback()
133           Exception done for MspInit and MspDeInit callbacks that are respectively
134           reset to the legacy weak (surcharged) functions in the @ref HAL_HASH_Init
135           and @ref HAL_HASH_DeInit only when these callbacks are null (not registered beforehand)
136           If not, MspInit or MspDeInit are not null, the @ref HAL_HASH_Init and @ref HAL_HASH_DeInit
137           keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
138 
139           Callbacks can be registered/unregistered in READY state only.
140           Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
141           in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
142           during the Init/DeInit.
143           In that case first register the MspInit/MspDeInit user callbacks
144           using @ref HAL_HASH_RegisterCallback before calling @ref HAL_HASH_DeInit
145           or @ref HAL_HASH_Init function.
146 
147           When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or
148           not defined, the callback registering feature is not available
149           and weak (surcharged) callbacks are used.
150 
151   @endverbatim
152   ******************************************************************************
153   * @attention
154   *
155   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
156   *
157   * Redistribution and use in source and binary forms, with or without modification,
158   * are permitted provided that the following conditions are met:
159   *   1. Redistributions of source code must retain the above copyright notice,
160   *      this list of conditions and the following disclaimer.
161   *   2. Redistributions in binary form must reproduce the above copyright notice,
162   *      this list of conditions and the following disclaimer in the documentation
163   *      and/or other materials provided with the distribution.
164   *   3. Neither the name of STMicroelectronics nor the names of its contributors
165   *      may be used to endorse or promote products derived from this software
166   *      without specific prior written permission.
167   *
168   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
169   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
170   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
171   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
172   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
173   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
174   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
175   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
176   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
177   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
178   *
179   ******************************************************************************
180   */
181 
182 /* Includes ------------------------------------------------------------------*/
183 #include "stm32l4xx_hal.h"
184 
185 
186 /** @addtogroup STM32L4xx_HAL_Driver
187   * @{
188   */
189 #if defined (HASH)
190 
191 /** @defgroup HASH  HASH
192   * @brief HASH HAL module driver.
193   * @{
194   */
195 
196 #ifdef HAL_HASH_MODULE_ENABLED
197 
198 /* Private typedef -----------------------------------------------------------*/
199 /* Private define ------------------------------------------------------------*/
200 /** @defgroup HASH_Private_Constants HASH Private Constants
201   * @{
202   */
203 
204 /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status
205   * @{
206   */
207 #define HASH_DIGEST_CALCULATION_NOT_STARTED       ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */
208 #define HASH_DIGEST_CALCULATION_STARTED           ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register     */
209 /**
210   * @}
211   */
212 
213 /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers
214   * @{
215   */
216 #define HASH_NUMBER_OF_CSR_REGISTERS              54U     /*!< Number of Context Swap Registers */
217 /**
218   * @}
219   */
220 
221 /** @defgroup HASH_TimeOut_Value HASH TimeOut Value
222   * @{
223   */
224 #define HASH_TIMEOUTVALUE                         1000U   /*!< Time-out value  */
225 /**
226   * @}
227   */
228 
229 /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit
230   * @{
231   */
232 #define HASH_DMA_SUSPENSION_WORDS_LIMIT             20U   /*!< Number of words below which DMA suspension is aborted */
233 /**
234   * @}
235   */
236 
237 /**
238   * @}
239   */
240 
241 /* Private macro -------------------------------------------------------------*/
242 /* Private variables ---------------------------------------------------------*/
243 /* Private function prototypes -----------------------------------------------*/
244 /** @defgroup HASH_Private_Functions HASH Private Functions
245   * @{
246   */
247 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma);
248 static void HASH_DMAError(DMA_HandleTypeDef *hdma);
249 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size);
250 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, uint32_t Timeout);
251 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size);
252 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash);
253 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash);
254 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout);
255 /**
256   * @}
257   */
258 
259 /** @defgroup HASH_Exported_Functions HASH Exported Functions
260   * @{
261   */
262 
263 /** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions
264  *  @brief    Initialization, configuration and call-back functions.
265  *
266 @verbatim
267  ===============================================================================
268               ##### Initialization and de-initialization functions #####
269  ===============================================================================
270     [..]  This section provides functions allowing to:
271       (+) Initialize the HASH according to the specified parameters
272           in the HASH_InitTypeDef and create the associated handle
273       (+) DeInitialize the HASH peripheral
274       (+) Initialize the HASH MCU Specific Package (MSP)
275       (+) DeInitialize the HASH MSP
276 
277     [..]  This section provides as well call back functions definitions for user
278           code to manage:
279       (+) Input data transfer to IP completion
280       (+) Calculated digest retrieval completion
281       (+) Error management
282 
283 
284 
285 @endverbatim
286   * @{
287   */
288 
289 /**
290   * @brief  Initialize the HASH according to the specified parameters in the
291             HASH_HandleTypeDef and create the associated handle.
292   * @note   Only MDMAT and DATATYPE bits of HASH IP are set by HAL_HASH_Init(),
293   *         other configuration bits are set by HASH or HMAC processing APIs.
294   * @note   MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for
295   *         multi-buffer HASH processing, user needs to resort to
296   *         __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the
297   *         relevant APIs manage themselves the MDMAT bit.
298   * @param  hhash: HASH handle
299   * @retval HAL status
300   */
HAL_HASH_Init(HASH_HandleTypeDef * hhash)301 HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash)
302 {
303   /* Check the parameters */
304   assert_param(IS_HASH_DATATYPE(hhash->Init.DataType));
305 
306   /* Check the hash handle allocation */
307   if(hhash == NULL)
308   {
309     return HAL_ERROR;
310   }
311 
312 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
313   if (hhash->State == HAL_HASH_STATE_RESET)
314   {
315     /* Allocate lock resource and initialize it */
316     hhash->Lock = HAL_UNLOCKED;
317 
318     /* Reset Callback pointers in HAL_HASH_STATE_RESET only */
319     hhash->InCpltCallback =  HAL_HASH_InCpltCallback;     /* Legacy weak (surcharged) input completion callback */
320     hhash->DgstCpltCallback =  HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation completion callback */
321     hhash->ErrorCallback =  HAL_HASH_ErrorCallback;       /* Legacy weak (surcharged) error callback */
322     if(hhash->MspInitCallback == NULL)
323     {
324       hhash->MspInitCallback = HAL_HASH_MspInit;
325     }
326 
327     /* Init the low level hardware */
328     hhash->MspInitCallback(hhash);
329   }
330 #else
331   if(hhash->State == HAL_HASH_STATE_RESET)
332   {
333     /* Allocate lock resource and initialize it */
334     hhash->Lock = HAL_UNLOCKED;
335 
336     /* Init the low level hardware */
337     HAL_HASH_MspInit(hhash);
338   }
339 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
340 
341     /* Change the HASH state */
342   hhash->State = HAL_HASH_STATE_BUSY;
343 
344   /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */
345   hhash->HashInCount = 0;
346   hhash->HashBuffSize = 0;
347   hhash->HashITCounter = 0;
348   hhash->NbWordsAlreadyPushed = 0;
349   /* Reset digest calculation bridle (MDMAT bit control) */
350   hhash->DigestCalculationDisable = RESET;
351   /* Set phase to READY */
352   hhash->Phase = HAL_HASH_PHASE_READY;
353 
354   /* Set the data type bit */
355   MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType);
356   /* Reset MDMAT bit */
357 __HAL_HASH_RESET_MDMAT();
358   /* Reset HASH handle status */
359   hhash->Status = HAL_OK;
360 
361   /* Set the HASH state to Ready */
362   hhash->State = HAL_HASH_STATE_READY;
363 
364   /* Initialise the error code */
365   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
366 
367   /* Return function status */
368   return HAL_OK;
369 }
370 
371 /**
372   * @brief  DeInitialize the HASH peripheral.
373   * @param  hhash: HASH handle.
374   * @retval HAL status
375   */
HAL_HASH_DeInit(HASH_HandleTypeDef * hhash)376 HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash)
377 {
378   /* Check the HASH handle allocation */
379   if(hhash == NULL)
380   {
381     return HAL_ERROR;
382   }
383 
384   /* Change the HASH state */
385   hhash->State = HAL_HASH_STATE_BUSY;
386 
387   /* Set the default HASH phase */
388   hhash->Phase = HAL_HASH_PHASE_READY;
389 
390   /* Reset HashInCount, HashITCounter and HashBuffSize */
391   hhash->HashInCount = 0;
392   hhash->HashBuffSize = 0;
393   hhash->HashITCounter = 0;
394   /* Reset digest calculation bridle (MDMAT bit control) */
395   hhash->DigestCalculationDisable = RESET;
396 
397 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
398     if(hhash->MspDeInitCallback == NULL)
399     {
400       hhash->MspDeInitCallback = HAL_HASH_MspDeInit;
401     }
402 
403     /* DeInit the low level hardware */
404     hhash->MspDeInitCallback(hhash);
405 #else
406   /* DeInit the low level hardware: CLOCK, NVIC */
407   HAL_HASH_MspDeInit(hhash);
408 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
409 
410 
411   /* Reset HASH handle status */
412   hhash->Status = HAL_OK;
413 
414   /* Set the HASH state to Ready */
415   hhash->State = HAL_HASH_STATE_RESET;
416 
417   /* Initialise the error code */
418   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
419 
420   /* Return function status */
421   return HAL_OK;
422 }
423 
424 /**
425   * @brief  Initialize the HASH MSP.
426   * @param  hhash: HASH handle.
427   * @retval None
428   */
HAL_HASH_MspInit(HASH_HandleTypeDef * hhash)429 __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash)
430 {
431   /* Prevent unused argument(s) compilation warning */
432   UNUSED(hhash);
433 
434   /* NOTE : This function should not be modified; when the callback is needed,
435             HAL_HASH_MspInit() can be implemented in the user file.
436    */
437 }
438 
439 /**
440   * @brief  DeInitialize the HASH MSP.
441   * @param  hhash: HASH handle.
442   * @retval None
443   */
HAL_HASH_MspDeInit(HASH_HandleTypeDef * hhash)444 __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash)
445 {
446   /* Prevent unused argument(s) compilation warning */
447   UNUSED(hhash);
448 
449   /* NOTE : This function should not be modified; when the callback is needed,
450             HAL_HASH_MspDeInit() can be implemented in the user file.
451    */
452 }
453 
454 /**
455   * @brief  Input data transfer complete call back.
456   * @note   HAL_HASH_InCpltCallback() is called when the complete input message
457   *         has been fed to the IP. This API is invoked only when input data are
458   *         entered under interruption or thru DMA.
459   * @note   In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set),
460   *         HAL_HASH_InCpltCallback() is called at the end of each buffer feeding
461   *         to the IP.
462   * @param  hhash: HASH handle.
463   * @retval None
464   */
HAL_HASH_InCpltCallback(HASH_HandleTypeDef * hhash)465 __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash)
466 {
467   /* Prevent unused argument(s) compilation warning */
468   UNUSED(hhash);
469 
470   /* NOTE : This function should not be modified; when the callback is needed,
471             HAL_HASH_InCpltCallback() can be implemented in the user file.
472    */
473 }
474 
475 /**
476   * @brief  Digest computation complete call back.
477   * @note   HAL_HASH_DgstCpltCallback() is used under interruption, is not
478   *         relevant with DMA.
479   * @param  hhash: HASH handle.
480   * @retval None
481   */
HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef * hhash)482 __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash)
483 {
484   /* Prevent unused argument(s) compilation warning */
485   UNUSED(hhash);
486 
487   /* NOTE : This function should not be modified; when the callback is needed,
488             HAL_HASH_DgstCpltCallback() can be implemented in the user file.
489    */
490 }
491 
492 /**
493   * @brief  Error callback.
494   * @note   Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...)
495   *         to retrieve the error type.
496   * @param  hhash: HASH handle.
497   * @retval None
498   */
HAL_HASH_ErrorCallback(HASH_HandleTypeDef * hhash)499 __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash)
500 {
501   /* Prevent unused argument(s) compilation warning */
502   UNUSED(hhash);
503 
504   /* NOTE : This function should not be modified; when the callback is needed,
505             HAL_HASH_ErrorCallback() can be implemented in the user file.
506    */
507 }
508 
509 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
510 /**
511   * @brief  Register a User HASH Callback
512   *         To be used instead of the weak (surcharged) predefined callback
513   * @param hhash HASH handle
514   * @param CallbackID ID of the callback to be registered
515   *        This parameter can be one of the following values:
516   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
517   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
518   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
519   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
520   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
521   * @param pCallback pointer to the Callback function
522   * @retval status
523   */
HAL_HASH_RegisterCallback(HASH_HandleTypeDef * hhash,HAL_HASH_CallbackIDTypeDef CallbackID,pHASH_CallbackTypeDef pCallback)524 HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID, pHASH_CallbackTypeDef pCallback)
525 {
526   HAL_StatusTypeDef status = HAL_OK;
527 
528   if(pCallback == NULL)
529   {
530     /* Update the error code */
531     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
532     return HAL_ERROR;
533   }
534   /* Process locked */
535   __HAL_LOCK(hhash);
536 
537   if(HAL_HASH_STATE_READY == hhash->State)
538   {
539     switch (CallbackID)
540     {
541     case HAL_HASH_INPUTCPLT_CB_ID :
542       hhash->InCpltCallback = pCallback;
543       break;
544 
545     case HAL_HASH_DGSTCPLT_CB_ID :
546       hhash->DgstCpltCallback = pCallback;
547       break;
548 
549     case HAL_HASH_ERROR_CB_ID :
550       hhash->ErrorCallback = pCallback;
551       break;
552 
553     case HAL_HASH_MSPINIT_CB_ID :
554       hhash->MspInitCallback = pCallback;
555       break;
556 
557     case HAL_HASH_MSPDEINIT_CB_ID :
558       hhash->MspDeInitCallback = pCallback;
559       break;
560 
561     default :
562      /* Update the error code */
563      hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
564      /* update return status */
565       status =  HAL_ERROR;
566       break;
567     }
568   }
569   else if(HAL_HASH_STATE_RESET == hhash->State)
570   {
571     switch (CallbackID)
572     {
573     case HAL_HASH_MSPINIT_CB_ID :
574       hhash->MspInitCallback = pCallback;
575       break;
576 
577     case HAL_HASH_MSPDEINIT_CB_ID :
578       hhash->MspDeInitCallback = pCallback;
579       break;
580 
581     default :
582      /* Update the error code */
583      hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
584      /* update return status */
585       status =  HAL_ERROR;
586       break;
587     }
588   }
589   else
590   {
591     /* Update the error code */
592      hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
593      /* update return status */
594       status =  HAL_ERROR;
595   }
596 
597   /* Release Lock */
598   __HAL_UNLOCK(hhash);
599   return status;
600 }
601 
602 /**
603   * @brief  Unregister a HASH Callback
604   *         HASH Callback is redirected to the weak (surcharged) predefined callback
605   * @param hhash HASH handle
606   * @param CallbackID ID of the callback to be unregistered
607   *        This parameter can be one of the following values:
608   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
609   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
610   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
611   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
612   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
613   * @retval status
614   */
HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef * hhash,HAL_HASH_CallbackIDTypeDef CallbackID)615 HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID)
616 {
617 HAL_StatusTypeDef status = HAL_OK;
618 
619   /* Process locked */
620   __HAL_LOCK(hhash);
621 
622   if(HAL_HASH_STATE_READY == hhash->State)
623   {
624     switch (CallbackID)
625     {
626     case HAL_HASH_INPUTCPLT_CB_ID :
627       hhash->InCpltCallback = HAL_HASH_InCpltCallback;     /* Legacy weak (surcharged) input completion callback */
628       break;
629 
630     case HAL_HASH_DGSTCPLT_CB_ID :
631       hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation completion callback */
632       break;
633 
634     case HAL_HASH_ERROR_CB_ID :
635       hhash->ErrorCallback = HAL_HASH_ErrorCallback;       /* Legacy weak (surcharged) error callback */
636       break;
637 
638     case HAL_HASH_MSPINIT_CB_ID :
639       hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
640       break;
641 
642     case HAL_HASH_MSPDEINIT_CB_ID :
643       hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
644       break;
645 
646     default :
647      /* Update the error code */
648      hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
649      /* update return status */
650       status =  HAL_ERROR;
651       break;
652     }
653   }
654   else if(HAL_HASH_STATE_RESET == hhash->State)
655   {
656     switch (CallbackID)
657     {
658     case HAL_HASH_MSPINIT_CB_ID :
659       hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
660       break;
661 
662     case HAL_HASH_MSPDEINIT_CB_ID :
663       hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
664       break;
665 
666     default :
667      /* Update the error code */
668      hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
669      /* update return status */
670       status =  HAL_ERROR;
671       break;
672     }
673   }
674   else
675   {
676      /* Update the error code */
677      hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
678      /* update return status */
679       status =  HAL_ERROR;
680   }
681 
682   /* Release Lock */
683   __HAL_UNLOCK(hhash);
684   return status;
685 }
686 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
687 
688 /**
689   * @}
690   */
691 
692 /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode
693  *  @brief   HASH processing functions using polling mode.
694  *
695 @verbatim
696  ===============================================================================
697                  ##### Polling mode HASH processing functions #####
698  ===============================================================================
699     [..]  This section provides functions allowing to calculate in polling mode
700           the hash value using one of the following algorithms:
701       (+) MD5
702          (++) HAL_HASH_MD5_Start()
703          (++) HAL_HASH_MD5_Accumulate()
704       (+) SHA1
705          (++) HAL_HASH_SHA1_Start()
706          (++) HAL_HASH_SHA1_Accumulate()
707 
708     [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
709 
710     [..]  In case of multi-buffer HASH processing (a single digest is computed while
711           several buffers are fed to the IP), the user can resort to successive calls
712           to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call
713           to HAL_HASH_xxx_Start().
714 
715 @endverbatim
716   * @{
717   */
718 
719 /**
720   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
721   *         read the computed digest.
722   * @note   Digest is available in pOutBuffer.
723   * @param  hhash: HASH handle.
724   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
725   * @param  Size: length of the input buffer in bytes.
726   * @param  pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
727   * @param  Timeout: Timeout value
728   * @retval HAL status
729   */
HAL_HASH_MD5_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)730 HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
731 {
732   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
733 }
734 
735 /**
736   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
737   *         processes pInBuffer.
738   * @note   Consecutive calls to HAL_HASH_MD5_Accumulate() can be used to feed
739   *         several input buffers back-to-back to the IP that will yield a single
740   *         HASH signature once all buffers have been entered. Wrap-up of input
741   *         buffers feeding and retrieval of digest is done by a call to
742   *         HAL_HASH_MD5_Start().
743   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
744   *         the IP has already been initialized.
745   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Start()
746   *         to read it, feeding at the same time the last input buffer to the IP.
747   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
748   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Start() is able
749   *         to manage the ending buffer with a length in bytes not a multiple of 4.
750   * @param  hhash: HASH handle.
751   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
752   * @param  Size: length of the input buffer in bytes, must be a multiple of 4.
753   * @retval HAL status
754   */
HAL_HASH_MD5_Accumulate(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)755 HAL_StatusTypeDef HAL_HASH_MD5_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
756 {
757   return  HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_MD5);
758 }
759 
760 /**
761   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
762   *         read the computed digest.
763   * @note   Digest is available in pOutBuffer.
764   * @param  hhash: HASH handle.
765   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
766   * @param  Size: length of the input buffer in bytes.
767   * @param  pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
768   * @param  Timeout: Timeout value
769   * @retval HAL status
770   */
HAL_HASH_SHA1_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)771 HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
772 {
773   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
774 }
775 
776 /**
777   * @brief  If not already done, initialize the HASH peripheral in SHA1 mode then
778   *         processes pInBuffer.
779   * @note   Consecutive calls to HAL_HASH_SHA1_Accumulate() can be used to feed
780   *         several input buffers back-to-back to the IP that will yield a single
781   *         HASH signature once all buffers have been entered. Wrap-up of input
782   *         buffers feeding and retrieval of digest is done by a call to
783   *         HAL_HASH_SHA1_Start().
784   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
785   *         the IP has already been initialized.
786   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Start()
787   *         to read it, feeding at the same time the last input buffer to the IP.
788   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
789   *         HASH digest computation is corrupted. Only HAL_HASH_SHA1_Start() is able
790   *         to manage the ending buffer with a length in bytes not a multiple of 4.
791   * @param  hhash: HASH handle.
792   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
793   * @param  Size: length of the input buffer in bytes, must be a multiple of 4.
794   * @retval HAL status
795   */
HAL_HASH_SHA1_Accumulate(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)796 HAL_StatusTypeDef HAL_HASH_SHA1_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
797 {
798   return  HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA1);
799 }
800 
801 
802 /**
803   * @}
804   */
805 
806 /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode
807  *  @brief   HASH processing functions using interrupt mode.
808  *
809 @verbatim
810  ===============================================================================
811                  ##### Interruption mode HASH processing functions #####
812  ===============================================================================
813     [..]  This section provides functions allowing to calculate in interrupt mode
814           the hash value using one of the following algorithms:
815       (+) MD5
816          (++) HAL_HASH_MD5_Start_IT()
817       (+) SHA1
818          (++) HAL_HASH_SHA1_Start_IT()
819 
820     [..]  API HAL_HASH_IRQHandler() manages each HASH interruption.
821 
822     [..] Note that HAL_HASH_IRQHandler() manages as well HASH IP interruptions when in
823          HMAC processing mode.
824 
825 
826 @endverbatim
827   * @{
828   */
829 
830 /**
831   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
832   *         read the computed digest in interruption mode.
833   * @note   Digest is available in pOutBuffer.
834   * @param  hhash: HASH handle.
835   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
836   * @param  Size: length of the input buffer in bytes.
837   * @param  pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
838   * @retval HAL status
839   */
HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)840 HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
841 {
842   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_MD5);
843 }
844 
845 
846 /**
847   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
848   *         read the computed digest in interruption mode.
849   * @note   Digest is available in pOutBuffer.
850   * @param  hhash: HASH handle.
851   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
852   * @param  Size: length of the input buffer in bytes.
853   * @param  pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
854   * @retval HAL status
855   */
HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)856 HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
857 {
858   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA1);
859 }
860 
861 /**
862   * @brief Handle HASH interrupt request.
863   * @param hhash: HASH handle.
864   * @note  HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well.
865   * @note  In case of error reported during the HASH interruption processing,
866   *        HAL_HASH_ErrorCallback() API is called so that user code can
867   *        manage the error. The error type is available in hhash->Status field.
868   * @retval None
869   */
HAL_HASH_IRQHandler(HASH_HandleTypeDef * hhash)870 void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash)
871 {
872   hhash->Status = HASH_IT(hhash);
873   if (hhash->Status != HAL_OK)
874   {
875     hhash->ErrorCode |= HAL_HASH_ERROR_IT;
876 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
877     hhash->ErrorCallback(hhash);
878 #else
879     HAL_HASH_ErrorCallback(hhash);
880 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
881     /* After error handling by code user, reset HASH handle HAL status */
882     hhash->Status = HAL_OK;
883   }
884 }
885 
886 /**
887   * @}
888   */
889 
890 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode
891  *  @brief   HASH processing functions using DMA mode.
892  *
893 @verbatim
894  ===============================================================================
895                     ##### DMA mode HASH processing functions #####
896  ===============================================================================
897     [..]  This section provides functions allowing to calculate in DMA mode
898           the hash value using one of the following algorithms:
899       (+) MD5
900          (++) HAL_HASH_MD5_Start_DMA()
901          (++) HAL_HASH_MD5_Finish()
902       (+) SHA1
903          (++) HAL_HASH_SHA1_Start_DMA()
904          (++) HAL_HASH_SHA1_Finish()
905 
906     [..]  When resorting to DMA mode to enter the data in the IP, user must resort
907           to  HAL_HASH_xxx_Start_DMA() then read the resulting digest with
908           HAL_HASH_xxx_Finish().
909     [..]  In case of multi-buffer HASH processing, MDMAT bit must first be set before
910           the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be
911           reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally
912           retrieved thanks to HAL_HASH_xxx_Finish().
913 
914 @endverbatim
915   * @{
916   */
917 
918 /**
919   * @brief  Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer
920   *         to feed the input buffer to the IP.
921   * @note   Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must
922   *         be called to retrieve the computed digest.
923   * @param  hhash: HASH handle.
924   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
925   * @param  Size: length of the input buffer in bytes.
926   * @retval HAL status
927   */
HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)928 HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
929 {
930   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
931 }
932 
933 /**
934   * @brief  Return the computed digest in MD5 mode.
935   * @note   The API waits for DCIS to be set then reads the computed digest.
936   * @note   HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in
937   *         HMAC MD5 mode.
938   * @param  hhash: HASH handle.
939   * @param  pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
940   * @param  Timeout: Timeout value.
941   * @retval HAL status
942   */
HAL_HASH_MD5_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)943 HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
944 {
945    return HASH_Finish(hhash, pOutBuffer, Timeout);
946 }
947 
948 /**
949   * @brief  Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer
950   *         to feed the input buffer to the IP.
951   * @note   Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must
952   *         be called to retrieve the computed digest.
953   * @param  hhash: HASH handle.
954   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
955   * @param  Size: length of the input buffer in bytes.
956   * @retval HAL status
957   */
HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)958 HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
959 {
960   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
961 }
962 
963 
964 /**
965   * @brief  Return the computed digest in SHA1 mode.
966   * @note   The API waits for DCIS to be set then reads the computed digest.
967   * @note   HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in
968   *         HMAC SHA1 mode.
969   * @param  hhash: HASH handle.
970   * @param  pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
971   * @param  Timeout: Timeout value.
972   * @retval HAL status
973   */
HAL_HASH_SHA1_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)974 HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
975 {
976    return HASH_Finish(hhash, pOutBuffer, Timeout);
977 }
978 
979 /**
980   * @}
981   */
982 
983 /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode
984  *  @brief   HMAC processing functions using polling mode.
985  *
986 @verbatim
987  ===============================================================================
988                  ##### Polling mode HMAC processing functions #####
989  ===============================================================================
990     [..]  This section provides functions allowing to calculate in polling mode
991           the HMAC value using one of the following algorithms:
992       (+) MD5
993          (++) HAL_HMAC_MD5_Start()
994       (+) SHA1
995          (++) HAL_HMAC_SHA1_Start()
996 
997 
998 @endverbatim
999   * @{
1000   */
1001 
1002 /**
1003   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1004   *         read the computed digest.
1005   * @note   Digest is available in pOutBuffer.
1006   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1007   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1008   * @param  hhash: HASH handle.
1009   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
1010   * @param  Size: length of the input buffer in bytes.
1011   * @param  pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
1012   * @param  Timeout: Timeout value.
1013   * @retval HAL status
1014   */
HAL_HMAC_MD5_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)1015 HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
1016 {
1017   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
1018 }
1019 
1020 /**
1021   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1022   *         read the computed digest.
1023   * @note   Digest is available in pOutBuffer.
1024   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1025   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1026   * @param  hhash: HASH handle.
1027   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
1028   * @param  Size: length of the input buffer in bytes.
1029   * @param  pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
1030   * @param  Timeout: Timeout value.
1031   * @retval HAL status
1032   */
HAL_HMAC_SHA1_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)1033 HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
1034 {
1035   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
1036 }
1037 
1038 /**
1039   * @}
1040   */
1041 
1042 
1043 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
1044  *  @brief   HMAC processing functions using interrupt mode.
1045  *
1046 @verbatim
1047  ===============================================================================
1048                  ##### Interrupt mode HMAC processing functions #####
1049  ===============================================================================
1050     [..]  This section provides functions allowing to calculate in interrupt mode
1051           the HMAC value using one of the following algorithms:
1052       (+) MD5
1053          (++) HAL_HMAC_MD5_Start_IT()
1054       (+) SHA1
1055          (++) HAL_HMAC_SHA1_Start_IT()
1056 
1057 @endverbatim
1058   * @{
1059   */
1060 
1061 
1062 /**
1063   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1064   *         read the computed digest in interrupt mode.
1065   * @note   Digest is available in pOutBuffer.
1066   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1067   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1068   * @param  hhash: HASH handle.
1069   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
1070   * @param  Size: length of the input buffer in bytes.
1071   * @param  pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
1072   * @retval HAL status
1073   */
HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1074 HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
1075 {
1076   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
1077 }
1078 
1079 /**
1080   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1081   *         read the computed digest in interrupt mode.
1082   * @note   Digest is available in pOutBuffer.
1083   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1084   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1085   * @param  hhash: HASH handle.
1086   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
1087   * @param  Size: length of the input buffer in bytes.
1088   * @param  pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
1089   * @retval HAL status
1090   */
HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1091 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
1092 {
1093   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
1094 }
1095 
1096 /**
1097   * @}
1098   */
1099 
1100 
1101 
1102 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
1103  *  @brief   HMAC processing functions using DMA modes.
1104  *
1105 @verbatim
1106  ===============================================================================
1107                  ##### DMA mode HMAC processing functions #####
1108  ===============================================================================
1109     [..]  This section provides functions allowing to calculate in DMA mode
1110           the HMAC value using one of the following algorithms:
1111       (+) MD5
1112          (++) HAL_HMAC_MD5_Start_DMA()
1113       (+) SHA1
1114          (++) HAL_HMAC_SHA1_Start_DMA()
1115 
1116     [..]  When resorting to DMA mode to enter the data in the IP for HMAC processing,
1117           user must resort to  HAL_HMAC_xxx_Start_DMA() then read the resulting digest
1118           with HAL_HASH_xxx_Finish().
1119 
1120 @endverbatim
1121   * @{
1122   */
1123 
1124 
1125 /**
1126   * @brief  Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
1127   *         DMA transfers to feed the key and the input buffer to the IP.
1128   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1129   *         to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
1130   *         the computed digest.
1131   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1132   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1133   * @note   If MDMAT bit is set before calling this function (multi-buffer
1134   *          HASH processing case), the input buffer size (in bytes) must be
1135   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
1136   *          For the processing of the last buffer of the thread, MDMAT bit must
1137   *          be reset and the buffer length (in bytes) doesn't have to be a
1138   *          multiple of 4.
1139   * @param  hhash: HASH handle.
1140   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
1141   * @param  Size: length of the input buffer in bytes.
1142   * @retval HAL status
1143   */
HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1144 HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1145 {
1146   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
1147 }
1148 
1149 
1150 /**
1151   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
1152   *         DMA transfers to feed the key and the input buffer to the IP.
1153   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1154   *         to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
1155   *         the computed digest.
1156   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1157   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1158   * @note   If MDMAT bit is set before calling this function (multi-buffer
1159   *          HASH processing case), the input buffer size (in bytes) must be
1160   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
1161   *          For the processing of the last buffer of the thread, MDMAT bit must
1162   *          be reset and the buffer length (in bytes) doesn't have to be a
1163   *          multiple of 4.
1164   * @param  hhash: HASH handle.
1165   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
1166   * @param  Size: length of the input buffer in bytes.
1167   * @retval HAL status
1168   */
HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1169 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1170 {
1171   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1172 }
1173 
1174 /**
1175   * @}
1176   */
1177 
1178 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
1179  *  @brief   Peripheral State functions.
1180  *
1181 @verbatim
1182  ===============================================================================
1183                       ##### Peripheral State methods #####
1184  ===============================================================================
1185     [..]
1186     This section permits to get in run-time the state and the peripheral handle
1187     status of the peripheral:
1188       (+) HAL_HASH_GetState()
1189       (+) HAL_HASH_GetStatus()
1190 
1191     [..]
1192     Additionally, this subsection provides functions allowing to save and restore
1193     the HASH or HMAC processing context in case of calculation suspension:
1194       (+) HAL_HASH_ContextSaving()
1195       (+) HAL_HASH_ContextRestoring()
1196 
1197     [..]
1198     This subsection provides functions allowing to suspend the HASH processing
1199       (+) when input are fed to the IP by software
1200           (++) HAL_HASH_SwFeed_ProcessSuspend()
1201       (+) when input are fed to the IP by DMA
1202           (++) HAL_HASH_DMAFeed_ProcessSuspend()
1203 
1204 
1205 
1206 @endverbatim
1207   * @{
1208   */
1209 
1210 /**
1211   * @brief  Return the HASH handle state.
1212   * @note   The API yields the current state of the handle (BUSY, READY,...).
1213   * @param  hhash: HASH handle.
1214   * @retval HAL HASH state
1215   */
HAL_HASH_GetState(HASH_HandleTypeDef * hhash)1216 HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash)
1217 {
1218   return hhash->State;
1219 }
1220 
1221 
1222 /**
1223   * @brief Return the HASH HAL status.
1224   * @note  The API yields the HAL status of the handle: it is the result of the
1225   *        latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
1226   * @param  hhash: HASH handle.
1227   * @retval HAL status
1228   */
HAL_HASH_GetStatus(HASH_HandleTypeDef * hhash)1229 HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash)
1230 {
1231   return hhash->Status;
1232 }
1233 
1234 /**
1235   * @brief  Save the HASH context in case of processing suspension.
1236   * @param  hhash: HASH handle.
1237   * @param  pMemBuffer: pointer to the memory buffer where the HASH context
1238   *         is saved.
1239   * @note   The IMR, STR, CR then all the CSR registers are saved
1240   *         in that order. Only the r/w bits are read to be restored later on.
1241   * @note   By default, all the context swap registers (there are
1242   *         HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
1243   * @note   pMemBuffer points to a buffer allocated by the user. The buffer size
1244   *         must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
1245   * @retval None
1246   */
HAL_HASH_ContextSaving(HASH_HandleTypeDef * hhash,uint8_t * pMemBuffer)1247 void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t* pMemBuffer)
1248 {
1249   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1250   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1251   uint32_t i;
1252 
1253   /* Prevent unused argument(s) compilation warning */
1254   UNUSED(hhash);
1255 
1256   /* Save IMR register content */
1257   *(uint32_t*)(mem_ptr) = READ_BIT(HASH->IMR,HASH_IT_DINI|HASH_IT_DCI);
1258   mem_ptr+=4U;
1259   /* Save STR register content */
1260   *(uint32_t*)(mem_ptr) = READ_BIT(HASH->STR,HASH_STR_NBLW);
1261   mem_ptr+=4U;
1262   /* Save CR register content */
1263   *(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);
1264   mem_ptr+=4U;
1265   /* By default, save all CSRs registers */
1266   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0U; i--)
1267   {
1268     *(uint32_t*)(mem_ptr) = *(uint32_t*)(csr_ptr);
1269     mem_ptr+=4U;
1270     csr_ptr+=4U;
1271   }
1272 }
1273 
1274 
1275 /**
1276   * @brief  Restore the HASH context in case of processing resumption.
1277   * @param  hhash: HASH handle.
1278   * @param  pMemBuffer: pointer to the memory buffer where the HASH context
1279   *         is stored.
1280   * @note   The IMR, STR, CR then all the CSR registers are restored
1281   *         in that order. Only the r/w bits are restored.
1282   * @note   By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
1283   *         of those) are restored (all of them have been saved by default
1284   *         beforehand).
1285   * @retval None
1286   */
HAL_HASH_ContextRestoring(HASH_HandleTypeDef * hhash,uint8_t * pMemBuffer)1287 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t* pMemBuffer)
1288 {
1289   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1290   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1291   uint32_t i;
1292 
1293   /* Prevent unused argument(s) compilation warning */
1294   UNUSED(hhash);
1295 
1296   /* Restore IMR register content */
1297   WRITE_REG(HASH->IMR, (*(uint32_t*)(mem_ptr)));
1298   mem_ptr+=4U;
1299   /* Restore STR register content */
1300   WRITE_REG(HASH->STR, (*(uint32_t*)(mem_ptr)));
1301   mem_ptr+=4U;
1302   /* Restore CR register content */
1303   WRITE_REG(HASH->CR, (*(uint32_t*)(mem_ptr)));
1304   mem_ptr+=4U;
1305 
1306   /* Reset the HASH processor before restoring the Context
1307   Swap Registers (CSR) */
1308   __HAL_HASH_INIT();
1309 
1310   /* By default, restore all CSR registers */
1311   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0U; i--)
1312   {
1313     WRITE_REG((*(uint32_t*)(csr_ptr)), (*(uint32_t*)(mem_ptr)));
1314     mem_ptr+=4U;
1315     csr_ptr+=4U;
1316   }
1317 }
1318 
1319 
1320 /**
1321   * @brief  Initiate HASH processing suspension when in polling or interruption mode.
1322   * @param  hhash: HASH handle.
1323   * @note   Set the handle field SuspendRequest to the appropriate value so that
1324   *         the on-going HASH processing is suspended as soon as the required
1325   *         conditions are met. Note that the actual suspension is carried out
1326   *         by the functions HASH_WriteData() in polling mode and HASH_IT() in
1327   *         interruption mode.
1328   * @retval None
1329   */
HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef * hhash)1330 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1331 {
1332   /* Set Handle Suspend Request field */
1333   hhash->SuspendRequest = HAL_HASH_SUSPEND;
1334 }
1335 
1336 /**
1337   * @brief  Suspend the HASH processing when in DMA mode.
1338   * @param  hhash: HASH handle.
1339   * @note   When suspension attempt occurs at the very end of a DMA transfer and
1340   *         all the data have already been entered in the IP, hhash->State is
1341   *         set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
1342   *         recommended to wrap-up the processing in reading the digest as usual.
1343   * @retval HAL status
1344   */
HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef * hhash)1345 HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1346 {
1347   uint32_t tmp_remaining_DMATransferSize_inWords;
1348   uint32_t tmp_initial_DMATransferSize_inWords;
1349   uint32_t tmp_words_already_pushed;
1350 
1351   if (hhash->State == HAL_HASH_STATE_READY)
1352   {
1353     return HAL_ERROR;
1354   }
1355   else
1356   {
1357 
1358    /* Make sure there is enough time to suspend the processing */
1359     tmp_remaining_DMATransferSize_inWords = ((DMA_Channel_TypeDef *)hhash->hdmain->Instance)->CNDTR;
1360     if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT)
1361     {
1362       /* No suspension attempted since almost to the end of the transferred data. */
1363       /* Best option for user code is to wrap up low priority message hashing     */
1364       return HAL_ERROR;
1365     }
1366 
1367     /* Wait for DMAS to be reset */
1368     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1369     {
1370        return HAL_TIMEOUT;
1371     }
1372 
1373     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1374     {
1375       return HAL_ERROR;
1376     }
1377 
1378     /* Wait for DMAS to be set */
1379     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK)
1380     {
1381        return HAL_TIMEOUT;
1382     }
1383 
1384     /* Disable DMA channel */
1385     /*
1386     Note that the Abort function will
1387     - clear the transfer error flags
1388     - unlock
1389     - set the State
1390     */
1391     if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK)
1392     {
1393       return HAL_ERROR;
1394     }
1395 
1396     /* Clear DMAE bit */
1397     CLEAR_BIT(HASH->CR,HASH_CR_DMAE);
1398 
1399     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1400     {
1401       return HAL_TIMEOUT;
1402     }
1403 
1404     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1405     {
1406       return HAL_ERROR;
1407     }
1408 
1409     /* At this point, DMA interface is disabled and no transfer is on-going */
1410     /* Retrieve from the DMA handle how many words remain to be written */
1411     tmp_remaining_DMATransferSize_inWords = ((DMA_Channel_TypeDef *)hhash->hdmain->Instance)->CNDTR;
1412 
1413     if (tmp_remaining_DMATransferSize_inWords == 0U)
1414     {
1415       /* All the DMA transfer is actually done. Suspension occurred at the very end
1416          of the transfer. Either the digest computation is about to start (HASH case)
1417          or processing is about to move from one step to another (HMAC case).
1418          In both cases, the processing can't be suspended at this point. It is
1419          safer to
1420          - retrieve the low priority block digest before starting the high
1421            priority block processing (HASH case)
1422          - re-attempt a new suspension (HMAC case)
1423          */
1424       return HAL_ERROR;
1425     }
1426     else
1427     {
1428 
1429       /* Compute how many words were supposed to be transferred by DMA */
1430       tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount%4U)!=0U) ?  ((hhash->HashInCount+3U)/4U): (hhash->HashInCount/4U));
1431 
1432       /* If discrepancy between the number of words reported by DMA IP and the numbers of words entered as reported
1433         by HASH IP, correct it */
1434       /* tmp_words_already_pushed reflects the number of words that were already pushed before
1435          the start of DMA transfer (multi-buffer processing case) */
1436       tmp_words_already_pushed = hhash->NbWordsAlreadyPushed;
1437       if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) %16U)  != HASH_NBW_PUSHED())
1438       {
1439         tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */
1440       }
1441 
1442       /* Accordingly, update the input pointer that points at the next word to be transferred to the IP by DMA */
1443       hhash->pHashInBuffPtr +=  4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ;
1444 
1445       /* And store in HashInCount the remaining size to transfer (in bytes) */
1446       hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords;
1447 
1448     }
1449 
1450     /* Set State as suspended */
1451     hhash->State = HAL_HASH_STATE_SUSPENDED;
1452 
1453     return HAL_OK;
1454 
1455   }
1456 }
1457 
1458 /**
1459   * @brief  Return the HASH handle error code.
1460   * @param  hhash: pointer to a HASH_HandleTypeDef structure.
1461   * @retval HASH Error Code
1462 */
HAL_HASH_GetError(HASH_HandleTypeDef * hhash)1463 uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash)
1464 {
1465   /* Return HASH Error Code */
1466   return hhash->ErrorCode;
1467 }
1468 /**
1469   * @}
1470   */
1471 
1472 
1473 /**
1474   * @}
1475   */
1476 
1477 /** @defgroup HASH_Private_Functions HASH Private Functions
1478   * @{
1479   */
1480 
1481 /**
1482   * @brief DMA HASH Input Data transfer completion callback.
1483   * @param hdma: DMA handle.
1484   * @note  In case of HMAC processing, HASH_DMAXferCplt() initiates
1485   *        the next DMA transfer for the following HMAC step.
1486   * @retval None
1487   */
HASH_DMAXferCplt(DMA_HandleTypeDef * hdma)1488 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma)
1489 {
1490   HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1491   uint32_t inputaddr;
1492   uint32_t buffersize;
1493   HAL_StatusTypeDef status ;
1494 
1495   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1496   {
1497 
1498     /* Disable the DMA transfer */
1499     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1500 
1501     if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U)
1502     {
1503       /* If no HMAC processing, input data transfer is now over */
1504 
1505       /* Change the HASH state to ready */
1506       hhash->State = HAL_HASH_STATE_READY;
1507 
1508       /* Call Input data transfer complete call back */
1509 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1510       hhash->InCpltCallback(hhash);
1511 #else
1512       HAL_HASH_InCpltCallback(hhash);
1513 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1514 
1515     }
1516     else
1517     {
1518       /* HMAC processing: depending on the current HMAC step and whether or
1519       not multi-buffer processing is on-going, the next step is initiated
1520       and MDMAT bit is set.  */
1521 
1522 
1523       if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
1524       {
1525         /* This is the end of HMAC processing */
1526 
1527         /* Change the HASH state to ready */
1528         hhash->State = HAL_HASH_STATE_READY;
1529 
1530         /* Call Input data transfer complete call back
1531         (note that the last DMA transfer was that of the key
1532         for the outer HASH operation). */
1533 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1534         hhash->InCpltCallback(hhash);
1535 #else
1536         HAL_HASH_InCpltCallback(hhash);
1537 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1538 
1539         return;
1540       }
1541       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
1542       {
1543         inputaddr = (uint32_t)hhash->pHashMsgBuffPtr;     /* DMA transfer start address */
1544         buffersize = hhash->HashBuffSize;                 /* DMA transfer size (in bytes) */
1545         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
1546 
1547         /* In case of suspension request, save the new starting parameters */
1548         hhash->HashInCount = hhash->HashBuffSize;         /* Initial DMA transfer size (in bytes) */
1549         hhash->pHashInBuffPtr  = hhash->pHashMsgBuffPtr ; /* DMA transfer start address           */
1550 
1551         hhash->NbWordsAlreadyPushed = 0U;                  /* Reset number of words already pushed */
1552         /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */
1553         if (hhash->DigestCalculationDisable != RESET)
1554         {
1555           /* Digest calculation is disabled: Step 2 must start with MDMAT bit set,
1556           no digest calculation will be triggered at the end of the input buffer feeding to the IP */
1557           __HAL_HASH_SET_MDMAT();
1558         }
1559       }
1560       else  /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
1561       {
1562         if (hhash->DigestCalculationDisable != RESET)
1563         {
1564           /* No automatic move to Step 3 as a new message buffer will be fed to the IP
1565           (case of multi-buffer HMAC processing):
1566           DCAL must not be set.
1567           Phase remains in Step 2, MDMAT remains set at this point.
1568           Change the HASH state to ready and call Input data transfer complete call back. */
1569           hhash->State = HAL_HASH_STATE_READY;
1570 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1571           hhash->InCpltCallback(hhash);
1572 #else
1573           HAL_HASH_InCpltCallback(hhash);
1574 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1575           return ;
1576         }
1577         else
1578         {
1579           /* Digest calculation is not disabled (case of single buffer input or last buffer
1580           of multi-buffer HMAC processing) */
1581           inputaddr = (uint32_t)hhash->Init.pKey;       /* DMA transfer start address */
1582           buffersize = hhash->Init.KeySize;             /* DMA transfer size (in bytes) */
1583           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;    /* Move phase from Step 2 to Step 3 */
1584           /* In case of suspension request, save the new starting parameters */
1585           hhash->HashInCount = hhash->Init.KeySize;     /* Initial size for second DMA transfer (input data) */
1586           hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* address passed to DMA, now entering data message */
1587 
1588           hhash->NbWordsAlreadyPushed = 0U;              /* Reset number of words already pushed */
1589         }
1590       }
1591 
1592     /* Configure the Number of valid bits in last word of the message */
1593     __HAL_HASH_SET_NBVALIDBITS(buffersize);
1594 
1595       /* Set the HASH DMA transfert completion call back */
1596       hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
1597 
1598       /* Enable the DMA In DMA Stream */
1599     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((buffersize%4U)!=0U) ? ((buffersize+3U)/4U):(buffersize/4U)));
1600 
1601     /* Enable DMA requests */
1602     SET_BIT(HASH->CR, HASH_CR_DMAE);
1603 
1604           /* Return function status */
1605       if (status != HAL_OK)
1606       {
1607         /* Update DAC state machine to error */
1608         hhash->State = HAL_HASH_STATE_ERROR;
1609       }
1610       else
1611       {
1612         /* Change DAC state */
1613         hhash->State = HAL_HASH_STATE_READY;
1614       }
1615   }
1616   }
1617 
1618   return;
1619 }
1620 
1621 /**
1622   * @brief DMA HASH communication error callback.
1623   * @param hdma: DMA handle.
1624   * @note  HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
1625   *        can contain user code to manage the error.
1626   * @retval None
1627   */
HASH_DMAError(DMA_HandleTypeDef * hdma)1628 static void HASH_DMAError(DMA_HandleTypeDef *hdma)
1629 {
1630   HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1631 
1632   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1633   {
1634     hhash->ErrorCode |= HAL_HASH_ERROR_DMA;
1635     /* Set HASH state to ready to prevent any blocking issue in user code
1636        present in HAL_HASH_ErrorCallback() */
1637     hhash->State= HAL_HASH_STATE_READY;
1638     /* Set HASH handle status to error */
1639     hhash->Status = HAL_ERROR;
1640 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1641     hhash->ErrorCallback(hhash);
1642 #else
1643     HAL_HASH_ErrorCallback(hhash);
1644 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1645     /* After error handling by code user, reset HASH handle HAL status */
1646     hhash->Status = HAL_OK;
1647 
1648   }
1649 }
1650 
1651 /**
1652   * @brief  Feed the input buffer to the HASH IP.
1653   * @param  hhash: HASH handle.
1654   * @param  pInBuffer: pointer to input buffer.
1655   * @param  Size: the size of input buffer in bytes.
1656   * @note   HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
1657   *         or not the HASH processing must be suspended. If this is the case, the
1658   *         processing is suspended when possible and the IP feeding point reached at
1659   *         suspension time is stored in the handle for resumption later on.
1660   * @retval HAL status
1661   */
HASH_WriteData(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1662 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1663 {
1664   uint32_t buffercounter;
1665   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
1666 
1667   for(buffercounter = 0U; buffercounter < Size; buffercounter+=4U)
1668   {
1669     /* Write input data 4 bytes at a time */
1670     HASH->DIN = *(uint32_t*)inputaddr;
1671     inputaddr+=4U;
1672 
1673     /* If the suspension flag has been raised and if the processing is not about
1674        to end, suspend processing */
1675     if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4U) < Size))
1676     {
1677       /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
1678          in the input buffer */
1679       if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
1680       {
1681         /* Reset SuspendRequest */
1682         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
1683 
1684         /* Depending whether the key or the input data were fed to the IP, the feeding point
1685            reached at suspension time is not saved in the same handle fields */
1686         if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
1687         {
1688           /* Save current reading and writing locations of Input and Output buffers */
1689           hhash->pHashInBuffPtr =  (uint8_t *)inputaddr;
1690           /* Save the number of bytes that remain to be processed at this point */
1691           hhash->HashInCount    =  Size - (buffercounter + 4U);
1692         }
1693         else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
1694         {
1695           /* Save current reading and writing locations of Input and Output buffers */
1696           hhash->pHashKeyBuffPtr  =  (uint8_t *)inputaddr;
1697           /* Save the number of bytes that remain to be processed at this point */
1698           hhash->HashKeyCount  =  Size - (buffercounter + 4U);
1699         }
1700         else
1701         {
1702           /* Unexpected phase: unlock process and report error */
1703           hhash->State = HAL_HASH_STATE_READY;
1704           __HAL_UNLOCK(hhash);
1705           return HAL_ERROR;
1706         }
1707 
1708         /* Set the HASH state to Suspended and exit to stop entering data */
1709         hhash->State = HAL_HASH_STATE_SUSPENDED;
1710 
1711         return HAL_OK;
1712       } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))  */
1713     } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
1714   }   /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4)                 */
1715 
1716   /* At this point, all the data have been entered to the IP: exit */
1717   return  HAL_OK;
1718 }
1719 
1720 /**
1721   * @brief  Retrieve the message digest.
1722   * @param  pMsgDigest: pointer to the computed digest.
1723   * @param  Size: message digest size in bytes.
1724   * @retval None
1725   */
HASH_GetDigest(uint8_t * pMsgDigest,uint8_t Size)1726 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
1727 {
1728   uint32_t msgdigest = (uint32_t)pMsgDigest;
1729 
1730   switch(Size)
1731   {
1732     /* Read the message digest */
1733     case 16:  /* MD5 */
1734       *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
1735       msgdigest+=4U;
1736       *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
1737       msgdigest+=4U;
1738       *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
1739       msgdigest+=4U;
1740       *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
1741     break;
1742     case 20:  /* SHA1 */
1743       *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
1744       msgdigest+=4U;
1745       *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
1746       msgdigest+=4U;
1747       *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
1748       msgdigest+=4U;
1749       *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
1750       msgdigest+=4U;
1751       *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
1752     break;
1753   case 28:  /* SHA224 */
1754     *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
1755     msgdigest+=4U;
1756     *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
1757     msgdigest+=4U;
1758     *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
1759     msgdigest+=4U;
1760     *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
1761     msgdigest+=4U;
1762     *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
1763     msgdigest+=4U;
1764     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
1765     msgdigest+=4U;
1766     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
1767     break;
1768   case 32:   /* SHA256 */
1769     *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
1770     msgdigest+=4U;
1771     *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
1772     msgdigest+=4U;
1773     *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
1774     msgdigest+=4U;
1775     *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
1776     msgdigest+=4U;
1777     *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
1778     msgdigest+=4U;
1779     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
1780     msgdigest+=4U;
1781     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
1782     msgdigest+=4U;
1783     *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
1784     break;
1785     default:
1786     break;
1787   }
1788 }
1789 
1790 
1791 
1792 /**
1793   * @brief  Handle HASH processing Timeout.
1794   * @param  hhash: HASH handle.
1795   * @param  Flag: specifies the HASH flag to check.
1796   * @param  Status: the Flag status (SET or RESET).
1797   * @param  Timeout: Timeout duration.
1798   * @retval HAL status
1799   */
HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef * hhash,uint32_t Flag,FlagStatus Status,uint32_t Timeout)1800 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, uint32_t Timeout)
1801 {
1802   uint32_t tickstart = HAL_GetTick();
1803 
1804   /* Wait until flag is set */
1805   if(Status == RESET)
1806   {
1807     while(__HAL_HASH_GET_FLAG(Flag) == RESET)
1808     {
1809       /* Check for the Timeout */
1810       if(Timeout != HAL_MAX_DELAY)
1811       {
1812         if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U))
1813         {
1814           /* Set State to Ready to be able to restart later on */
1815           hhash->State  = HAL_HASH_STATE_READY;
1816           /* Store time out issue in handle status */
1817           hhash->Status = HAL_TIMEOUT;
1818 
1819           /* Process Unlocked */
1820           __HAL_UNLOCK(hhash);
1821 
1822           return HAL_TIMEOUT;
1823         }
1824       }
1825     }
1826   }
1827   else
1828   {
1829     while(__HAL_HASH_GET_FLAG(Flag) != RESET)
1830     {
1831       /* Check for the Timeout */
1832       if(Timeout != HAL_MAX_DELAY)
1833       {
1834         if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U))
1835         {
1836           /* Set State to Ready to be able to restart later on */
1837           hhash->State  = HAL_HASH_STATE_READY;
1838           /* Store time out issue in handle status */
1839           hhash->Status = HAL_TIMEOUT;
1840 
1841           /* Process Unlocked */
1842           __HAL_UNLOCK(hhash);
1843 
1844           return HAL_TIMEOUT;
1845         }
1846       }
1847     }
1848   }
1849   return HAL_OK;
1850 }
1851 
1852 
1853 /**
1854   * @brief  HASH processing in interruption mode.
1855   * @param  hhash: HASH handle.
1856   * @note   HASH_IT() regularly reads hhash->SuspendRequest to check whether
1857   *         or not the HASH processing must be suspended. If this is the case, the
1858   *         processing is suspended when possible and the IP feeding point reached at
1859   *         suspension time is stored in the handle for resumption later on.
1860   * @retval HAL status
1861   */
HASH_IT(HASH_HandleTypeDef * hhash)1862 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
1863 {
1864   if (hhash->State == HAL_HASH_STATE_BUSY)
1865   {
1866     /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
1867     if(hhash->HashITCounter == 0U)
1868     {
1869       /* Disable Interrupts */
1870       __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1871       /* HASH state set back to Ready to prevent any issue in user code
1872          present in HAL_HASH_ErrorCallback() */
1873       hhash->State = HAL_HASH_STATE_READY;
1874       return HAL_ERROR;
1875     }
1876     else if (hhash->HashITCounter == 1U)
1877     {
1878      /* This is the first call to HASH_IT, the first input data are about to be
1879         entered in the IP. A specific processing is carried out at this point to
1880         start-up the processing. */
1881       hhash->HashITCounter = 2U;
1882     }
1883     else
1884     {
1885       /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
1886         the HASH processing or the end of the current step for HMAC processing. */
1887       hhash->HashITCounter = 3U;
1888     }
1889 
1890     /* If digest is ready */
1891     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
1892     {
1893       /* Read the digest */
1894       HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
1895 
1896       /* Disable Interrupts */
1897       __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1898       /* Change the HASH state */
1899       hhash->State = HAL_HASH_STATE_READY;
1900       /* Call digest computation complete call back */
1901 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1902       hhash->DgstCpltCallback(hhash);
1903 #else
1904       HAL_HASH_DgstCpltCallback(hhash);
1905 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1906 
1907       return HAL_OK;
1908     }
1909 
1910     /* If IP ready to accept new data */
1911     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
1912     {
1913 
1914       /* If the suspension flag has been raised and if the processing is not about
1915          to end, suspend processing */
1916       if ( (hhash->HashInCount != 0U) &&  (hhash->SuspendRequest == HAL_HASH_SUSPEND))
1917       {
1918         /* Disable Interrupts */
1919         __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1920 
1921         /* Reset SuspendRequest */
1922         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
1923 
1924         /* Change the HASH state */
1925         hhash->State = HAL_HASH_STATE_SUSPENDED;
1926 
1927         return HAL_OK;
1928       }
1929 
1930       /* Enter input data in the IP thru HASH_Write_Block_Data() call and
1931         check whether the digest calculation has been triggered */
1932       if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
1933       {
1934         /* Call Input data transfer complete call back
1935            (called at the end of each step for HMAC) */
1936 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1937         hhash->InCpltCallback(hhash);
1938 #else
1939         HAL_HASH_InCpltCallback(hhash);
1940 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1941 
1942         if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
1943         {
1944           /* Wait until IP is not busy anymore */
1945           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1946           {
1947             /* Disable Interrupts */
1948             __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1949             return HAL_TIMEOUT;
1950           }
1951           /* Initialization start for HMAC STEP 2 */
1952           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
1953           __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);  /* Set NBLW for the input message */
1954           hhash->HashInCount = hhash->HashBuffSize;         /* Set the input data size (in bytes) */
1955           hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr;   /* Set the input data address */
1956           hhash->HashITCounter = 1;                         /* Set ITCounter to 1 to indicate the start of a new phase */
1957           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);               /* Enable IT (was disabled in HASH_Write_Block_Data) */
1958         }
1959         else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
1960         {
1961           /* Wait until IP is not busy anymore */
1962           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1963           {
1964             /* Disable Interrupts */
1965             __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1966             return HAL_TIMEOUT;
1967           }
1968           /* Initialization start for HMAC STEP 3 */
1969           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;         /* Move phase from Step 2 to Step 3 */
1970           __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);   /* Set NBLW for the key */
1971           hhash->HashInCount = hhash->Init.KeySize;          /* Set the key size (in bytes) */
1972           hhash->pHashInBuffPtr = hhash->Init.pKey;          /* Set the key address */
1973           hhash->HashITCounter = 1;                          /* Set ITCounter to 1 to indicate the start of a new phase */
1974           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);                /* Enable IT (was disabled in HASH_Write_Block_Data) */
1975         }
1976         else
1977         {
1978           /* Nothing to do */
1979         }
1980       } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
1981     }  /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
1982 
1983     /* Return function status */
1984     return HAL_OK;
1985   }
1986   else
1987   {
1988     return HAL_BUSY;
1989   }
1990 }
1991 
1992 
1993 /**
1994   * @brief  Write a block of data in HASH IP in interruption mode.
1995   * @param  hhash: HASH handle.
1996   * @note   HASH_Write_Block_Data() is called under interruption by HASH_IT().
1997   * @retval HAL status
1998   */
HASH_Write_Block_Data(HASH_HandleTypeDef * hhash)1999 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
2000 {
2001   uint32_t inputaddr;
2002   uint32_t buffercounter;
2003   uint32_t inputcounter;
2004   uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
2005 
2006   /* If there are more than 64 bytes remaining to be entered */
2007   if(hhash->HashInCount > 64U)
2008   {
2009     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2010     /* Write the Input block in the Data IN register
2011       (16 32-bit words, or 64 bytes are entered) */
2012     for(buffercounter = 0U; buffercounter < 64U; buffercounter+=4U)
2013     {
2014       HASH->DIN = *(uint32_t*)inputaddr;
2015       inputaddr+=4U;
2016     }
2017     /* If this is the start of input data entering, an additional word
2018       must be entered to start up the HASH processing */
2019     if(hhash->HashITCounter == 2U)
2020     {
2021       HASH->DIN = *(uint32_t*)inputaddr;
2022       if(hhash->HashInCount >= 68U)
2023       {
2024         /* There are still data waiting to be entered in the IP.
2025            Decrement buffer counter and set pointer to the proper
2026            memory location for the next data entering round. */
2027         hhash->HashInCount -= 68U;
2028         hhash->pHashInBuffPtr+= 68U;
2029       }
2030       else
2031       {
2032         /* All the input buffer has been fed to the HW. */
2033         hhash->HashInCount = 0U;
2034       }
2035     }
2036     else
2037     {
2038       /* 64 bytes have been entered and there are still some remaining:
2039          Decrement buffer counter and set pointer to the proper
2040         memory location for the next data entering round.*/
2041       hhash->HashInCount -= 64U;
2042       hhash->pHashInBuffPtr+= 64U;
2043     }
2044   }
2045   else
2046   {
2047     /* 64 or less bytes remain to be entered. This is the last
2048       data entering round. */
2049 
2050     /* Get the buffer address */
2051     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2052     /* Get the buffer counter */
2053     inputcounter = hhash->HashInCount;
2054     /* Disable Interrupts */
2055     __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
2056 
2057     /* Write the Input block in the Data IN register */
2058     for(buffercounter = 0U; buffercounter < ((inputcounter+3U)/4U); buffercounter++)
2059     {
2060       HASH->DIN = *(uint32_t*)inputaddr;
2061       inputaddr+=4U;
2062     }
2063     /* Start the Digest calculation */
2064     __HAL_HASH_START_DIGEST();
2065     /* Return indication that digest calculation has started:
2066        this return value triggers the call to Input data transfer
2067        complete call back as well as the proper transition from
2068        one step to another in HMAC mode. */
2069     ret = HASH_DIGEST_CALCULATION_STARTED;
2070     /* Reset buffer counter */
2071     hhash->HashInCount = 0;
2072   }
2073 
2074   /* Return whether or digest calculation has started */
2075   return ret;
2076 }
2077 
2078 /**
2079   * @brief  HMAC processing in polling mode.
2080   * @param  hhash: HASH handle.
2081   * @param  Timeout: Timeout value.
2082   * @retval HAL status
2083   */
HMAC_Processing(HASH_HandleTypeDef * hhash,uint32_t Timeout)2084 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
2085 {
2086   /* Ensure first that Phase is correct */
2087   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))
2088   {
2089     /* Change the HASH state */
2090     hhash->State = HAL_HASH_STATE_READY;
2091 
2092     /* Process Unlock */
2093     __HAL_UNLOCK(hhash);
2094 
2095     /* Return function status */
2096     return HAL_ERROR;
2097   }
2098 
2099   /* HMAC Step 1 processing */
2100   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2101   {
2102     /************************** STEP 1 ******************************************/
2103     /* Configure the Number of valid bits in last word of the message */
2104     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2105 
2106     /* Write input buffer in Data register */
2107     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2108     if (hhash->Status != HAL_OK)
2109     {
2110       return hhash->Status;
2111     }
2112 
2113     /* Check whether or not key entering process has been suspended */
2114     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2115     {
2116       /* Process Unlocked */
2117       __HAL_UNLOCK(hhash);
2118 
2119       /* Stop right there and return function status */
2120       return HAL_OK;
2121     }
2122 
2123     /* No processing suspension at this point: set DCAL bit. */
2124     __HAL_HASH_START_DIGEST();
2125 
2126     /* Wait for BUSY flag to be cleared */
2127     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2128     {
2129       return HAL_TIMEOUT;
2130     }
2131 
2132     /* Move from Step 1 to Step 2 */
2133     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
2134 
2135   }
2136 
2137   /* HMAC Step 2 processing.
2138      After phase check, HMAC_Processing() may
2139      - directly start up from this point in resumption case
2140        if the same Step 2 processing was suspended previously
2141     - or fall through from the Step 1 processing carried out hereabove */
2142   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2143   {
2144     /************************** STEP 2 ******************************************/
2145     /* Configure the Number of valid bits in last word of the message */
2146     __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
2147 
2148     /* Write input buffer in Data register */
2149     hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
2150     if (hhash->Status != HAL_OK)
2151     {
2152       return hhash->Status;
2153     }
2154 
2155     /* Check whether or not data entering process has been suspended */
2156     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2157     {
2158       /* Process Unlocked */
2159       __HAL_UNLOCK(hhash);
2160 
2161       /* Stop right there and return function status */
2162       return HAL_OK;
2163     }
2164 
2165     /* No processing suspension at this point: set DCAL bit. */
2166     __HAL_HASH_START_DIGEST();
2167 
2168     /* Wait for BUSY flag to be cleared */
2169     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2170     {
2171       return HAL_TIMEOUT;
2172     }
2173 
2174     /* Move from Step 2 to Step 3 */
2175     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
2176     /* In case Step 1 phase was suspended then resumed,
2177        set again Key input buffers and size before moving to
2178        next step */
2179     hhash->pHashKeyBuffPtr = hhash->Init.pKey;
2180     hhash->HashKeyCount    = hhash->Init.KeySize;
2181   }
2182 
2183 
2184  /* HMAC Step 3 processing.
2185      After phase check, HMAC_Processing() may
2186      - directly start up from this point in resumption case
2187        if the same Step 3 processing was suspended previously
2188     - or fall through from the Step 2 processing carried out hereabove */
2189   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
2190   {
2191     /************************** STEP 3 ******************************************/
2192     /* Configure the Number of valid bits in last word of the message */
2193     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2194 
2195     /* Write input buffer in Data register */
2196     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2197     if (hhash->Status != HAL_OK)
2198     {
2199       return hhash->Status;
2200     }
2201 
2202     /* Check whether or not key entering process has been suspended */
2203     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2204     {
2205       /* Process Unlocked */
2206       __HAL_UNLOCK(hhash);
2207 
2208       /* Stop right there and return function status */
2209       return HAL_OK;
2210     }
2211 
2212     /* No processing suspension at this point: start the Digest calculation. */
2213     __HAL_HASH_START_DIGEST();
2214 
2215     /* Wait for DCIS flag to be set */
2216      if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2217     {
2218       return HAL_TIMEOUT;
2219     }
2220 
2221     /* Read the message digest */
2222     HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2223   }
2224 
2225    /* Change the HASH state */
2226    hhash->State = HAL_HASH_STATE_READY;
2227 
2228    /* Process Unlock */
2229    __HAL_UNLOCK(hhash);
2230 
2231    /* Return function status */
2232    return HAL_OK;
2233 }
2234 
2235 
2236 /**
2237   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2238   *         read the computed digest.
2239   * @note   Digest is available in pOutBuffer.
2240   * @param  hhash: HASH handle.
2241   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
2242   * @param  Size: length of the input buffer in bytes.
2243   * @param  pOutBuffer: pointer to the computed digest.
2244   * @param  Timeout: Timeout value.
2245   * @param  Algorithm: HASH algorithm.
2246   * @retval HAL status
2247   */
HASH_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)2248 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout, uint32_t Algorithm)
2249 {
2250   uint8_t *pInBuffer_tmp;  /* input data address, input parameter of HASH_WriteData()         */
2251   uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
2252   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2253 
2254 
2255   /* Initiate HASH processing in case of start or resumption */
2256 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2257   {
2258     /* Check input parameters */
2259     if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
2260     {
2261       hhash->State = HAL_HASH_STATE_READY;
2262       return  HAL_ERROR;
2263     }
2264 
2265     /* Process Locked */
2266     __HAL_LOCK(hhash);
2267 
2268     /* Check if initialization phase has not been already performed */
2269     if(hhash->Phase == HAL_HASH_PHASE_READY)
2270     {
2271       /* Change the HASH state */
2272       hhash->State = HAL_HASH_STATE_BUSY;
2273 
2274       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2275       MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2276 
2277       /* Configure the number of valid bits in last word of the message */
2278       __HAL_HASH_SET_NBVALIDBITS(Size);
2279 
2280       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2281       input parameters of HASH_WriteData() */
2282       pInBuffer_tmp = pInBuffer;   /* pInBuffer_tmp is set to the input data address */
2283       Size_tmp = Size;             /* Size_tmp contains the input data size in bytes */
2284 
2285       /* Set the phase */
2286       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2287     }
2288     else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
2289     {
2290       /* if the IP has already been initialized, two cases are possible */
2291 
2292       /* Process resumption time ... */
2293       if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2294       {
2295         /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2296         to the API input parameters but to those saved beforehand by HASH_WriteData()
2297         when the processing was suspended */
2298         pInBuffer_tmp = hhash->pHashInBuffPtr;
2299         Size_tmp = hhash->HashInCount;
2300       }
2301       /* ... or multi-buffer HASH processing end */
2302       else
2303       {
2304         /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2305         input parameters of HASH_WriteData() */
2306         pInBuffer_tmp = pInBuffer;
2307         Size_tmp = Size;
2308         /* Configure the number of valid bits in last word of the message */
2309         __HAL_HASH_SET_NBVALIDBITS(Size);
2310       }
2311       /* Change the HASH state */
2312       hhash->State = HAL_HASH_STATE_BUSY;
2313     }
2314     else
2315     {
2316       /* Phase error */
2317       hhash->State = HAL_HASH_STATE_READY;
2318 
2319       /* Process Unlocked */
2320       __HAL_UNLOCK(hhash);
2321 
2322       /* Return function status */
2323       return HAL_ERROR;
2324     }
2325 
2326 
2327     /* Write input buffer in Data register */
2328     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2329     if (hhash->Status != HAL_OK)
2330     {
2331       return hhash->Status;
2332     }
2333 
2334     /* If the process has not been suspended, carry on to digest calculation */
2335     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2336     {
2337       /* Start the Digest calculation */
2338       __HAL_HASH_START_DIGEST();
2339 
2340       /* Wait for DCIS flag to be set */
2341       if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2342       {
2343         return HAL_TIMEOUT;
2344       }
2345 
2346       /* Read the message digest */
2347       HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
2348 
2349       /* Change the HASH state */
2350       hhash->State = HAL_HASH_STATE_READY;
2351 
2352     }
2353 
2354     /* Process Unlocked */
2355     __HAL_UNLOCK(hhash);
2356 
2357     /* Return function status */
2358     return HAL_OK;
2359 
2360   }
2361   else
2362   {
2363     return HAL_BUSY;
2364   }
2365 }
2366 
2367 
2368 /**
2369   * @brief  If not already done, initialize the HASH peripheral then
2370   *         processes pInBuffer.
2371   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
2372   *         the IP has already been initialized.
2373   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2374   *         HASH digest computation is corrupted.
2375   * @param  hhash: HASH handle.
2376   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
2377   * @param  Size: length of the input buffer in bytes, must be a multiple of 4.
2378   * @param  Algorithm: HASH algorithm.
2379   * @retval HAL status
2380   */
HASH_Accumulate(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)2381 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2382 {
2383   uint8_t *pInBuffer_tmp;   /* input data address, input parameter of HASH_WriteData()         */
2384   uint32_t Size_tmp;  /* input data size (in bytes), input parameter of HASH_WriteData() */
2385   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2386 
2387   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2388    assert_param(IS_HASH_POLLING_MULTIBUFFER_SIZE(Size));
2389 
2390   /* Initiate HASH processing in case of start or resumption */
2391 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2392   {
2393     /* Check input parameters */
2394     if ((pInBuffer == NULL) || (Size == 0U))
2395     {
2396       hhash->State = HAL_HASH_STATE_READY;
2397       return  HAL_ERROR;
2398     }
2399 
2400      /* Process Locked */
2401     __HAL_LOCK(hhash);
2402 
2403     /* If resuming the HASH processing */
2404     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2405     {
2406       /* Change the HASH state */
2407       hhash->State = HAL_HASH_STATE_BUSY;
2408 
2409       /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2410          to the API input parameters but to those saved beforehand by HASH_WriteData()
2411          when the processing was suspended */
2412       pInBuffer_tmp = hhash->pHashInBuffPtr;  /* pInBuffer_tmp is set to the input data address */
2413       Size_tmp = hhash->HashInCount;          /* Size_tmp contains the input data size in bytes */
2414 
2415     }
2416     else
2417     {
2418       /* Change the HASH state */
2419       hhash->State = HAL_HASH_STATE_BUSY;
2420 
2421       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2422          input parameters of HASH_WriteData() */
2423       pInBuffer_tmp = pInBuffer;    /* pInBuffer_tmp is set to the input data address */
2424       Size_tmp = Size;              /* Size_tmp contains the input data size in bytes */
2425 
2426       /* Check if initialization phase has already be performed */
2427       if(hhash->Phase == HAL_HASH_PHASE_READY)
2428       {
2429         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2430         MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2431       }
2432 
2433       /* Set the phase */
2434       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2435 
2436     }
2437 
2438     /* Write input buffer in Data register */
2439     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2440     if (hhash->Status != HAL_OK)
2441     {
2442       return hhash->Status;
2443     }
2444 
2445     /* If the process has not been suspended, move the state to Ready */
2446     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2447     {
2448       /* Change the HASH state */
2449       hhash->State = HAL_HASH_STATE_READY;
2450     }
2451 
2452     /* Process Unlocked */
2453     __HAL_UNLOCK(hhash);
2454 
2455     /* Return function status */
2456     return HAL_OK;
2457 
2458   }
2459   else
2460   {
2461     return HAL_BUSY;
2462   }
2463 
2464 
2465 }
2466 
2467 
2468 /**
2469   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2470   *         read the computed digest in interruption mode.
2471   * @note   Digest is available in pOutBuffer.
2472   * @param  hhash: HASH handle.
2473   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
2474   * @param  Size: length of the input buffer in bytes.
2475   * @param  pOutBuffer: pointer to the computed digest.
2476   * @param  Algorithm: HASH algorithm.
2477   * @retval HAL status
2478   */
HASH_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)2479 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Algorithm)
2480 {
2481    HAL_HASH_StateTypeDef State_tmp = hhash->State;
2482 
2483   /* If State is ready or suspended, start or resume IT-based HASH processing */
2484 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2485   {
2486     /* Check input parameters */
2487     if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
2488     {
2489       hhash->State = HAL_HASH_STATE_READY;
2490       return  HAL_ERROR;
2491     }
2492 
2493     /* Process Locked */
2494     __HAL_LOCK(hhash);
2495 
2496     /* Change the HASH state */
2497     hhash->State = HAL_HASH_STATE_BUSY;
2498 
2499     /* Initialize IT counter */
2500     hhash->HashITCounter = 1;
2501 
2502     /* Check if initialization phase has already be performed */
2503     if(hhash->Phase == HAL_HASH_PHASE_READY)
2504     {
2505       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2506       MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2507 
2508       /* Configure the number of valid bits in last word of the message */
2509      __HAL_HASH_SET_NBVALIDBITS(Size);
2510 
2511 
2512       hhash->HashInCount = Size;               /* Counter used to keep track of number of data
2513                                                   to be fed to the IP */
2514       hhash->pHashInBuffPtr = pInBuffer;       /* Points at data which will be fed to the IP at
2515                                                   the next interruption */
2516      /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2517         the information describing where the HASH process is stopped.
2518         These variables are used later on to resume the HASH processing at the
2519         correct location. */
2520 
2521       hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2522     }
2523 
2524     /* Set the phase */
2525     hhash->Phase = HAL_HASH_PHASE_PROCESS;
2526 
2527     /* Process Unlock */
2528     __HAL_UNLOCK(hhash);
2529 
2530     /* Enable Interrupts */
2531     __HAL_HASH_ENABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
2532 
2533     /* Return function status */
2534     return HAL_OK;
2535   }
2536   else
2537   {
2538     return HAL_BUSY;
2539   }
2540 
2541 }
2542 
2543 
2544 /**
2545   * @brief  Initialize the HASH peripheral then initiate a DMA transfer
2546   *         to feed the input buffer to the IP.
2547   * @note   If MDMAT bit is set before calling this function (multi-buffer
2548   *          HASH processing case), the input buffer size (in bytes) must be
2549   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
2550   *          For the processing of the last buffer of the thread, MDMAT bit must
2551   *          be reset and the buffer length (in bytes) doesn't have to be a
2552   *          multiple of 4.
2553   * @param  hhash: HASH handle.
2554   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
2555   * @param  Size: length of the input buffer in bytes.
2556   * @param  Algorithm: HASH algorithm.
2557   * @retval HAL status
2558   */
HASH_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)2559 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2560 {
2561   uint32_t inputaddr;
2562   uint32_t inputSize;
2563   HAL_StatusTypeDef status ;
2564   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2565 
2566 #if defined (HASH_CR_MDMAT)
2567   /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
2568      (case of multi-buffer HASH processing) */
2569   assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
2570 #endif /* MDMA defined*/
2571    /* If State is ready or suspended, start or resume polling-based HASH processing */
2572 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2573   {
2574     /* Check input parameters */
2575     if ( (pInBuffer == NULL ) || (Size == 0U) ||
2576     /* Check phase coherency. Phase must be
2577        either READY (fresh start)
2578        or PROCESS (multi-buffer HASH management) */
2579        ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
2580     {
2581       hhash->State = HAL_HASH_STATE_READY;
2582       return  HAL_ERROR;
2583     }
2584 
2585 
2586     /* Process Locked */
2587     __HAL_LOCK(hhash);
2588 
2589     /* If not a resumption case */
2590     if (hhash->State == HAL_HASH_STATE_READY)
2591     {
2592       /* Change the HASH state */
2593       hhash->State = HAL_HASH_STATE_BUSY;
2594 
2595       /* Check if initialization phase has already been performed.
2596          If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
2597          API is processing a new input data message in case of multi-buffer HASH
2598          computation. */
2599       if(hhash->Phase == HAL_HASH_PHASE_READY)
2600       {
2601         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2602         MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2603 
2604         /* Set the phase */
2605         hhash->Phase = HAL_HASH_PHASE_PROCESS;
2606       }
2607 
2608       /* Configure the Number of valid bits in last word of the message */
2609       __HAL_HASH_SET_NBVALIDBITS(Size);
2610 
2611       inputaddr = (uint32_t)pInBuffer;     /* DMA transfer start address   */
2612       inputSize = Size;                    /* DMA transfer size (in bytes) */
2613 
2614       /* In case of suspension request, save the starting parameters */
2615       hhash->pHashInBuffPtr =  pInBuffer;  /* DMA transfer start address   */
2616       hhash->HashInCount = Size;           /* DMA transfer size (in bytes) */
2617 
2618     }
2619     /* If resumption case */
2620     else
2621     {
2622       /* Change the HASH state */
2623       hhash->State = HAL_HASH_STATE_BUSY;
2624 
2625       /* Resumption case, inputaddr and inputSize are not set to the API input parameters
2626          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
2627          processing was suspended */
2628       inputaddr = (uint32_t)hhash->pHashInBuffPtr;  /* DMA transfer start address   */
2629       inputSize = hhash->HashInCount;               /* DMA transfer size (in bytes) */
2630 
2631     }
2632 
2633     /* Set the HASH DMA transfert complete callback */
2634     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
2635     /* Set the DMA error callback */
2636     hhash->hdmain->XferErrorCallback = HASH_DMAError;
2637 
2638     /* Store number of words already pushed to manage proper DMA processing suspension */
2639     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
2640 
2641     /* Enable the DMA In DMA Stream */
2642     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((inputSize%4U)!=0U) ? ((inputSize+3U)/4U):(inputSize/4U)));
2643 
2644     /* Enable DMA requests */
2645     SET_BIT(HASH->CR, HASH_CR_DMAE);
2646 
2647     /* Process Unlock */
2648     __HAL_UNLOCK(hhash);
2649 
2650     /* Return function status */
2651     if (status != HAL_OK)
2652     {
2653       /* Update HASH state machine to error */
2654       hhash->State = HAL_HASH_STATE_ERROR;
2655     }
2656     else
2657     {
2658       /* Change HASH state */
2659       hhash->State = HAL_HASH_STATE_READY;
2660     }
2661 
2662     return status;
2663   }
2664   else
2665   {
2666     return HAL_BUSY;
2667   }
2668 }
2669 
2670 /**
2671   * @brief  Return the computed digest.
2672   * @note   The API waits for DCIS to be set then reads the computed digest.
2673   * @param  hhash: HASH handle.
2674   * @param  pOutBuffer: pointer to the computed digest.
2675   * @param  Timeout: Timeout value.
2676   * @retval HAL status
2677   */
HASH_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)2678 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
2679 {
2680 
2681   if(hhash->State == HAL_HASH_STATE_READY)
2682   {
2683     /* Check parameter */
2684     if (pOutBuffer == NULL)
2685     {
2686       return  HAL_ERROR;
2687     }
2688 
2689     /* Process Locked */
2690     __HAL_LOCK(hhash);
2691 
2692     /* Change the HASH state to busy */
2693     hhash->State = HAL_HASH_STATE_BUSY;
2694 
2695     /* Wait for DCIS flag to be set */
2696     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2697     {
2698       return HAL_TIMEOUT;
2699     }
2700 
2701     /* Read the message digest */
2702     HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
2703 
2704     /* Change the HASH state to ready */
2705     hhash->State = HAL_HASH_STATE_READY;
2706 
2707     /* Process UnLock */
2708     __HAL_UNLOCK(hhash);
2709 
2710     /* Return function status */
2711     return HAL_OK;
2712 
2713   }
2714   else
2715   {
2716     return HAL_BUSY;
2717   }
2718 
2719 }
2720 
2721 
2722 /**
2723   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
2724   *         read the computed digest.
2725   * @note   Digest is available in pOutBuffer.
2726   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
2727   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
2728   * @param  hhash: HASH handle.
2729   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
2730   * @param  Size: length of the input buffer in bytes.
2731   * @param  pOutBuffer: pointer to the computed digest.
2732   * @param  Timeout: Timeout value.
2733   * @param  Algorithm: HASH algorithm.
2734   * @retval HAL status
2735   */
HMAC_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)2736 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout, uint32_t Algorithm)
2737 {
2738     HAL_HASH_StateTypeDef State_tmp = hhash->State;
2739 
2740    /* If State is ready or suspended, start or resume polling-based HASH processing */
2741 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2742   {
2743     /* Check input parameters */
2744     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || (pOutBuffer == NULL))
2745     {
2746       hhash->State = HAL_HASH_STATE_READY;
2747       return  HAL_ERROR;
2748     }
2749 
2750     /* Process Locked */
2751     __HAL_LOCK(hhash);
2752 
2753     /* Change the HASH state */
2754     hhash->State = HAL_HASH_STATE_BUSY;
2755 
2756     /* Check if initialization phase has already be performed */
2757     if(hhash->Phase == HAL_HASH_PHASE_READY)
2758     {
2759       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
2760       if(hhash->Init.KeySize > 64U)
2761       {
2762         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);
2763       }
2764       else
2765       {
2766         MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
2767       }
2768       /* Set the phase to Step 1 */
2769       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
2770       /* Resort to hhash internal fields to feed the IP.
2771          Parameters will be updated in case of suspension to contain the proper
2772          information at resumption time. */
2773       hhash->pHashOutBuffPtr  = pOutBuffer;            /* Output digest address                                              */
2774       hhash->pHashInBuffPtr   = pInBuffer;             /* Input data address, HMAC_Processing input parameter for Step 2     */
2775       hhash->HashInCount      = Size;                  /* Input data size, HMAC_Processing input parameter for Step 2        */
2776       hhash->HashBuffSize     = Size;                  /* Store the input buffer size for the whole HMAC process             */
2777       hhash->pHashKeyBuffPtr  = hhash->Init.pKey;      /* Key address, HMAC_Processing input parameter for Step 1 and Step 3 */
2778       hhash->HashKeyCount     = hhash->Init.KeySize;   /* Key size, HMAC_Processing input parameter for Step 1 and Step 3    */
2779     }
2780 
2781     /* Carry out HMAC processing */
2782     return HMAC_Processing(hhash, Timeout);
2783 
2784   }
2785   else
2786   {
2787     return HAL_BUSY;
2788   }
2789 }
2790 
2791 
2792 
2793 /**
2794   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
2795   *         read the computed digest in interruption mode.
2796   * @note   Digest is available in pOutBuffer.
2797   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
2798   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
2799   * @param  hhash: HASH handle.
2800   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
2801   * @param  Size: length of the input buffer in bytes.
2802   * @param  pOutBuffer: pointer to the computed digest.
2803   * @param  Algorithm: HASH algorithm.
2804   * @retval HAL status
2805   */
HMAC_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)2806 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Algorithm)
2807 {
2808     HAL_HASH_StateTypeDef State_tmp = hhash->State;
2809 
2810   /* If State is ready or suspended, start or resume IT-based HASH processing */
2811 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2812   {
2813     /* Check input parameters */
2814     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || (pOutBuffer == NULL))
2815     {
2816       hhash->State = HAL_HASH_STATE_READY;
2817       return  HAL_ERROR;
2818     }
2819 
2820     /* Process Locked */
2821     __HAL_LOCK(hhash);
2822 
2823     /* Change the HASH state */
2824     hhash->State = HAL_HASH_STATE_BUSY;
2825 
2826     /* Initialize IT counter */
2827     hhash->HashITCounter = 1;
2828 
2829     /* Check if initialization phase has already be performed */
2830     if (hhash->Phase == HAL_HASH_PHASE_READY)
2831     {
2832       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
2833       if(hhash->Init.KeySize > 64U)
2834       {
2835         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);
2836       }
2837       else
2838       {
2839         MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
2840       }
2841 
2842       /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
2843          to feed the IP whatever the HMAC step.
2844          Lines below are set to start HMAC Step 1 processing where key is entered first. */
2845       hhash->HashInCount     = hhash->Init.KeySize; /* Key size                      */
2846       hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* Key address                   */
2847 
2848       /* Store input and output parameters in handle fields to manage steps transition
2849          or possible HMAC suspension/resumption */
2850       hhash->pHashKeyBuffPtr = hhash->Init.pKey;    /* Key address                   */
2851       hhash->pHashMsgBuffPtr = pInBuffer;           /* Input message address         */
2852       hhash->HashBuffSize    = Size;                /* Input message size (in bytes) */
2853       hhash->pHashOutBuffPtr = pOutBuffer;          /* Output digest address         */
2854 
2855       /* Configure the number of valid bits in last word of the key */
2856       __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2857 
2858       /* Set the phase to Step 1 */
2859       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
2860     }
2861     else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
2862     {
2863       /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
2864 
2865     }
2866     else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2867     {
2868       /* Restart IT-based HASH processing after Step 2 suspension */
2869 
2870     }
2871     else
2872     {
2873       /* Error report as phase incorrect */
2874       /* Process Unlock */
2875       __HAL_UNLOCK(hhash);
2876       hhash->State = HAL_HASH_STATE_READY;
2877       return HAL_ERROR;
2878     }
2879 
2880     /* Process Unlock */
2881     __HAL_UNLOCK(hhash);
2882 
2883     /* Enable Interrupts */
2884     __HAL_HASH_ENABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
2885 
2886     /* Return function status */
2887     return HAL_OK;
2888   }
2889   else
2890   {
2891     return HAL_BUSY;
2892   }
2893 
2894 }
2895 
2896 
2897 
2898 /**
2899   * @brief  Initialize the HASH peripheral in HMAC mode then initiate the required
2900   *         DMA transfers to feed the key and the input buffer to the IP.
2901   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
2902   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
2903   * @note   In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
2904   *         be a multiple of 4 otherwise, the HASH digest computation is corrupted.
2905   *         Only the length of the last buffer of the thread doesn't have to be a
2906   *         multiple of 4.
2907   * @param  hhash: HASH handle.
2908   * @param  pInBuffer: pointer to the input buffer (buffer to be hashed).
2909   * @param  Size: length of the input buffer in bytes.
2910   * @param  Algorithm: HASH algorithm.
2911   * @retval HAL status
2912   */
HMAC_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)2913 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2914 {
2915   uint32_t inputaddr;
2916   uint32_t inputSize;
2917   HAL_StatusTypeDef status ;
2918   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2919    /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
2920       is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
2921    assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size));
2922   /* If State is ready or suspended, start or resume DMA-based HASH processing */
2923 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2924   {
2925     /* Check input parameters */
2926     if ((pInBuffer == NULL ) || (Size == 0U) || (hhash->Init.pKey == NULL ) || (hhash->Init.KeySize == 0U) ||
2927    /* Check phase coherency. Phase must be
2928        either READY (fresh start)
2929        or one of HMAC PROCESS steps (multi-buffer HASH management) */
2930        ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
2931     {
2932       hhash->State = HAL_HASH_STATE_READY;
2933       return  HAL_ERROR;
2934     }
2935 
2936 
2937     /* Process Locked */
2938     __HAL_LOCK(hhash);
2939 
2940     /* If not a case of resumption after suspension */
2941     if (hhash->State == HAL_HASH_STATE_READY)
2942     {
2943     /* Check whether or not initialization phase has already be performed */
2944     if(hhash->Phase == HAL_HASH_PHASE_READY)
2945     {
2946       /* Change the HASH state */
2947       hhash->State = HAL_HASH_STATE_BUSY;
2948       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
2949          At the same time, ensure MDMAT bit is cleared. */
2950       if(hhash->Init.KeySize > 64U)
2951       {
2952         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);
2953       }
2954       else
2955       {
2956         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);
2957       }
2958       /* Store input aparameters in handle fields to manage steps transition
2959          or possible HMAC suspension/resumption */
2960       hhash->HashInCount = hhash->Init.KeySize;   /* Initial size for first DMA transfer (key size)      */
2961       hhash->pHashKeyBuffPtr = hhash->Init.pKey;  /* Key address                                         */
2962       hhash->pHashInBuffPtr  = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
2963       hhash->pHashMsgBuffPtr = pInBuffer;         /* Input data address                                  */
2964       hhash->HashBuffSize = Size;                 /* input data size (in bytes)                          */
2965 
2966       /* Set DMA input parameters */
2967       inputaddr = (uint32_t)(hhash->Init.pKey);   /* Address passed to DMA (start by entering Key message) */
2968       inputSize = hhash->Init.KeySize;            /* Size for first DMA transfer (in bytes) */
2969 
2970       /* Configure the number of valid bits in last word of the key */
2971       __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2972 
2973       /* Set the phase to Step 1 */
2974       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
2975 
2976     }
2977       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2978     {
2979       /* Process a new input data message in case of multi-buffer HMAC processing
2980         (this is not a resumption case) */
2981 
2982       /* Change the HASH state */
2983       hhash->State = HAL_HASH_STATE_BUSY;
2984 
2985       /* Save input parameters to be able to manage possible suspension/resumption */
2986         hhash->HashInCount = Size;                /* Input message address       */
2987         hhash->pHashInBuffPtr = pInBuffer;        /* Input message size in bytes */
2988 
2989       /* Set DMA input parameters */
2990         inputaddr = (uint32_t)pInBuffer;           /* Input message address       */
2991         inputSize = Size;                          /* Input message size in bytes */
2992 
2993       if (hhash->DigestCalculationDisable == RESET)
2994       {
2995         /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
2996        __HAL_HASH_RESET_MDMAT();
2997         __HAL_HASH_SET_NBVALIDBITS(inputSize);
2998       }
2999     }
3000       else
3001       {
3002         /* Phase not aligned with handle READY state */
3003         __HAL_UNLOCK(hhash);
3004         /* Return function status */
3005         return HAL_ERROR;
3006       }
3007     }
3008     else
3009     {
3010        /* Resumption case (phase may be Step 1, 2 or 3) */
3011 
3012       /* Change the HASH state */
3013       hhash->State = HAL_HASH_STATE_BUSY;
3014 
3015       /* Set DMA input parameters at resumption location;
3016          inputaddr and inputSize are not set to the API input parameters
3017          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3018          processing was suspended. */
3019       inputaddr = (uint32_t)(hhash->pHashInBuffPtr);  /* Input message address       */
3020       inputSize = hhash->HashInCount;                 /* Input message size in bytes */
3021     }
3022 
3023 
3024     /* Set the HASH DMA transfert complete callback */
3025     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3026     /* Set the DMA error callback */
3027     hhash->hdmain->XferErrorCallback = HASH_DMAError;
3028 
3029     /* Store number of words already pushed to manage proper DMA processing suspension */
3030     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3031 
3032     /* Enable the DMA In DMA Stream */
3033     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN,  (((inputSize %4U)!=0U) ? ((inputSize+3U)/4U):(inputSize/4U)));
3034     /* Enable DMA requests */
3035     SET_BIT(HASH->CR, HASH_CR_DMAE);
3036 
3037     /* Process Unlocked */
3038     __HAL_UNLOCK(hhash);
3039 
3040     /* Return function status */
3041     if (status != HAL_OK)
3042     {
3043       /* Update HASH state machine to error */
3044       hhash->State = HAL_HASH_STATE_ERROR;
3045     }
3046     else
3047     {
3048       /* Change HASH state */
3049       hhash->State = HAL_HASH_STATE_READY;
3050     }
3051     /* Return function status */
3052     return status;
3053   }
3054   else
3055   {
3056     return HAL_BUSY;
3057   }
3058 }
3059 /**
3060   * @}
3061   */
3062 
3063 #endif /* HAL_HASH_MODULE_ENABLED */
3064 
3065 /**
3066   * @}
3067   */
3068 #endif /*  HASH*/
3069 /**
3070   * @}
3071   */
3072 
3073 
3074 
3075 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
3076