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