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;
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 uint32_t tmp;
1838
1839 for (buffercounter = 0U; buffercounter < Size / 4U; buffercounter++)
1840 {
1841 /* Write input data 4 bytes at a time */
1842 HASH->DIN = *(uint32_t *)inputaddr;
1843 inputaddr += 4U;
1844
1845 /* If the suspension flag has been raised and if the processing is not about
1846 to end, suspend processing */
1847 if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter * 4 + 4U) < Size))
1848 {
1849 /* wait for flag BUSY not set before Wait for DINIS = 1*/
1850 if (buffercounter * 4 >= 64U)
1851 {
1852 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1853 {
1854 return HAL_TIMEOUT;
1855 }
1856 }
1857 /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
1858 in the input buffer */
1859 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
1860 {
1861 /* Reset SuspendRequest */
1862 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
1863
1864 /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
1865 reached at suspension time is not saved in the same handle fields */
1866 if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
1867 {
1868 /* Save current reading and writing locations of Input and Output buffers */
1869 hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
1870 /* Save the number of bytes that remain to be processed at this point */
1871 hhash->HashInCount = Size - (buffercounter * 4 + 4U);
1872 }
1873 else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
1874 {
1875 /* Save current reading and writing locations of Input and Output buffers */
1876 hhash->pHashKeyBuffPtr = (uint8_t *)inputaddr;
1877 /* Save the number of bytes that remain to be processed at this point */
1878 hhash->HashKeyCount = Size - (buffercounter * 4 + 4U);
1879 }
1880 else
1881 {
1882 /* Unexpected phase: unlock process and report error */
1883 hhash->State = HAL_HASH_STATE_READY;
1884 __HAL_UNLOCK(hhash);
1885 return HAL_ERROR;
1886 }
1887
1888 /* Set the HASH state to Suspended and exit to stop entering data */
1889 hhash->State = HAL_HASH_STATE_SUSPENDED;
1890
1891 return HAL_OK;
1892 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) */
1893 } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
1894 } /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4) */
1895
1896 /* At this point, all the data have been entered to the Peripheral: exit */
1897
1898 if (Size % 4U != 0U)
1899 {
1900 if (hhash->Init.DataType == HASH_DATATYPE_16B)
1901 {
1902 /* Write remaining input data */
1903
1904 if (Size % 4U <= 2)
1905 {
1906 HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
1907 }
1908 if (Size % 4U == 3)
1909 {
1910 HASH->DIN = *(uint32_t *)inputaddr;
1911 }
1912
1913 }
1914 else if ((hhash->Init.DataType == HASH_DATATYPE_8B)
1915 || (hhash->Init.DataType == HASH_DATATYPE_1B)) /* byte swap or bit swap or */
1916 {
1917 /* Write remaining input data */
1918 if (Size % 4U == 1)
1919 {
1920 HASH->DIN = (uint32_t) * (uint8_t *)inputaddr;
1921 }
1922 if (Size % 4U == 2)
1923 {
1924 HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
1925 }
1926 if (Size % 4U == 3)
1927 {
1928 tmp = *(uint8_t *)inputaddr;
1929 tmp |= *(uint8_t *)(inputaddr + 1U) << 8U ;
1930 tmp |= *(uint8_t *)(inputaddr + 2U) << 16U;
1931 HASH->DIN = tmp;
1932 }
1933
1934 }
1935 else
1936 {
1937 HASH->DIN = *(uint32_t *)inputaddr;
1938 }
1939 /*hhash->HashInCount += 4U;*/
1940 }
1941
1942
1943 return HAL_OK;
1944 }
1945
1946 /**
1947 * @brief Retrieve the message digest.
1948 * @param pMsgDigest pointer to the computed digest.
1949 * @param Size message digest size in bytes.
1950 * @retval None
1951 */
HASH_GetDigest(uint8_t * pMsgDigest,uint8_t Size)1952 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
1953 {
1954 uint32_t msgdigest = (uint32_t)pMsgDigest;
1955
1956 switch (Size)
1957 {
1958 /* Read the message digest */
1959 case 16: /* MD5 */
1960 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1961 msgdigest += 4U;
1962 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1963 msgdigest += 4U;
1964 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1965 msgdigest += 4U;
1966 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1967 break;
1968 case 20: /* SHA1 */
1969 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1970 msgdigest += 4U;
1971 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1972 msgdigest += 4U;
1973 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1974 msgdigest += 4U;
1975 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1976 msgdigest += 4U;
1977 *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
1978 break;
1979 case 28: /* SHA224 */
1980 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1981 msgdigest += 4U;
1982 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1983 msgdigest += 4U;
1984 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1985 msgdigest += 4U;
1986 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1987 msgdigest += 4U;
1988 *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
1989 #if defined(HASH_CR_MDMAT)
1990 msgdigest += 4U;
1991 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
1992 msgdigest += 4U;
1993 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
1994 #endif /* HASH_CR_MDMAT*/
1995 break;
1996 case 32: /* SHA256 */
1997 *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1998 msgdigest += 4U;
1999 *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
2000 msgdigest += 4U;
2001 *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
2002 msgdigest += 4U;
2003 *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
2004 msgdigest += 4U;
2005 *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
2006 #if defined(HASH_CR_MDMAT)
2007 msgdigest += 4U;
2008 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
2009 msgdigest += 4U;
2010 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
2011 msgdigest += 4U;
2012 *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
2013 #endif /* HASH_CR_MDMAT*/
2014 break;
2015 default:
2016 break;
2017 }
2018 }
2019
2020
2021
2022 /**
2023 * @brief Handle HASH processing Timeout.
2024 * @param hhash HASH handle.
2025 * @param Flag specifies the HASH flag to check.
2026 * @param Status the Flag status (SET or RESET).
2027 * @param Timeout Timeout duration.
2028 * @retval HAL status
2029 */
HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef * hhash,uint32_t Flag,FlagStatus Status,uint32_t Timeout)2030 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
2031 uint32_t Timeout)
2032 {
2033 uint32_t tickstart = HAL_GetTick();
2034
2035 /* Wait until flag is set */
2036 if (Status == RESET)
2037 {
2038 while (__HAL_HASH_GET_FLAG(Flag) == RESET)
2039 {
2040 /* Check for the Timeout */
2041 if (Timeout != HAL_MAX_DELAY)
2042 {
2043 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
2044 {
2045 /* Set State to Ready to be able to restart later on */
2046 hhash->State = HAL_HASH_STATE_READY;
2047 /* Store time out issue in handle status */
2048 hhash->Status = HAL_TIMEOUT;
2049
2050 /* Process Unlocked */
2051 __HAL_UNLOCK(hhash);
2052
2053 return HAL_TIMEOUT;
2054 }
2055 }
2056 }
2057 }
2058 else
2059 {
2060 while (__HAL_HASH_GET_FLAG(Flag) != RESET)
2061 {
2062 /* Check for the Timeout */
2063 if (Timeout != HAL_MAX_DELAY)
2064 {
2065 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
2066 {
2067 /* Set State to Ready to be able to restart later on */
2068 hhash->State = HAL_HASH_STATE_READY;
2069 /* Store time out issue in handle status */
2070 hhash->Status = HAL_TIMEOUT;
2071
2072 /* Process Unlocked */
2073 __HAL_UNLOCK(hhash);
2074
2075 return HAL_TIMEOUT;
2076 }
2077 }
2078 }
2079 }
2080 return HAL_OK;
2081 }
2082
2083
2084 /**
2085 * @brief HASH processing in interruption mode.
2086 * @param hhash HASH handle.
2087 * @note HASH_IT() regularly reads hhash->SuspendRequest to check whether
2088 * or not the HASH processing must be suspended. If this is the case, the
2089 * processing is suspended when possible and the Peripheral feeding point reached at
2090 * suspension time is stored in the handle for resumption later on.
2091 * @retval HAL status
2092 */
HASH_IT(HASH_HandleTypeDef * hhash)2093 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
2094 {
2095 if (hhash->State == HAL_HASH_STATE_BUSY)
2096 {
2097 /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
2098 if (hhash->HashITCounter == 0U)
2099 {
2100 /* Disable Interrupts */
2101 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2102 /* HASH state set back to Ready to prevent any issue in user code
2103 present in HAL_HASH_ErrorCallback() */
2104 hhash->State = HAL_HASH_STATE_READY;
2105 return HAL_ERROR;
2106 }
2107 else if (hhash->HashITCounter == 1U)
2108 {
2109 /* This is the first call to HASH_IT, the first input data are about to be
2110 entered in the Peripheral. A specific processing is carried out at this point to
2111 start-up the processing. */
2112 hhash->HashITCounter = 2U;
2113 }
2114 else
2115 {
2116 /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
2117 the HASH processing or the end of the current step for HMAC processing. */
2118 hhash->HashITCounter = 3U;
2119 }
2120
2121 /* If digest is ready */
2122 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
2123 {
2124 /* Read the digest */
2125 HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2126
2127 /* Disable Interrupts */
2128 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2129 /* Change the HASH state */
2130 hhash->State = HAL_HASH_STATE_READY;
2131 /* Reset HASH state machine */
2132 hhash->Phase = HAL_HASH_PHASE_READY;
2133 /* Call digest computation complete call back */
2134 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2135 hhash->DgstCpltCallback(hhash);
2136 #else
2137 HAL_HASH_DgstCpltCallback(hhash);
2138 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2139
2140 return HAL_OK;
2141 }
2142
2143 /* If Peripheral ready to accept new data */
2144 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2145 {
2146
2147 /* If the suspension flag has been raised and if the processing is not about
2148 to end, suspend processing */
2149 if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
2150 {
2151 /* Disable Interrupts */
2152 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2153
2154 /* Reset SuspendRequest */
2155 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
2156
2157 /* Change the HASH state */
2158 hhash->State = HAL_HASH_STATE_SUSPENDED;
2159
2160 return HAL_OK;
2161 }
2162
2163 /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and
2164 check whether the digest calculation has been triggered */
2165 if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
2166 {
2167 /* Call Input data transfer complete call back
2168 (called at the end of each step for HMAC) */
2169 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2170 hhash->InCpltCallback(hhash);
2171 #else
2172 HAL_HASH_InCpltCallback(hhash);
2173 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2174
2175 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2176 {
2177 /* Wait until Peripheral is not busy anymore */
2178 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2179 {
2180 /* Disable Interrupts */
2181 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2182 return HAL_TIMEOUT;
2183 }
2184 /* Initialization start for HMAC STEP 2 */
2185 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */
2186 __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); /* Set NBLW for the input message */
2187 hhash->HashInCount = hhash->HashBuffSize; /* Set the input data size (in bytes) */
2188 hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr; /* Set the input data address */
2189 hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start
2190 of a new phase */
2191 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */
2192 }
2193 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2194 {
2195 /* Wait until Peripheral is not busy anymore */
2196 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2197 {
2198 /* Disable Interrupts */
2199 __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2200 return HAL_TIMEOUT;
2201 }
2202 /* Initialization start for HMAC STEP 3 */
2203 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */
2204 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); /* Set NBLW for the key */
2205 hhash->HashInCount = hhash->Init.KeySize; /* Set the key size (in bytes) */
2206 hhash->pHashInBuffPtr = hhash->Init.pKey; /* Set the key address */
2207 hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start
2208 of a new phase */
2209 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */
2210 }
2211 else
2212 {
2213 /* Nothing to do */
2214 }
2215 } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
2216 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
2217
2218 /* Return function status */
2219 return HAL_OK;
2220 }
2221 else
2222 {
2223 return HAL_BUSY;
2224 }
2225 }
2226
2227
2228 /**
2229 * @brief Write a block of data in HASH Peripheral in interruption mode.
2230 * @param hhash HASH handle.
2231 * @note HASH_Write_Block_Data() is called under interruption by HASH_IT().
2232 * @retval HAL status
2233 */
HASH_Write_Block_Data(HASH_HandleTypeDef * hhash)2234 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
2235 {
2236 uint32_t inputaddr;
2237 uint32_t buffercounter;
2238 uint32_t inputcounter;
2239 uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
2240
2241 /* If there are more than 64 bytes remaining to be entered */
2242 if (hhash->HashInCount > 64U)
2243 {
2244 inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2245 /* Write the Input block in the Data IN register
2246 (16 32-bit words, or 64 bytes are entered) */
2247 for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U)
2248 {
2249 HASH->DIN = *(uint32_t *)inputaddr;
2250 inputaddr += 4U;
2251 }
2252 /* If this is the start of input data entering, an additional word
2253 must be entered to start up the HASH processing */
2254 if (hhash->HashITCounter == 2U)
2255 {
2256 HASH->DIN = *(uint32_t *)inputaddr;
2257 if (hhash->HashInCount >= 68U)
2258 {
2259 /* There are still data waiting to be entered in the Peripheral.
2260 Decrement buffer counter and set pointer to the proper
2261 memory location for the next data entering round. */
2262 hhash->HashInCount -= 68U;
2263 hhash->pHashInBuffPtr += 68U;
2264 }
2265 else
2266 {
2267 /* All the input buffer has been fed to the HW. */
2268 hhash->HashInCount = 0U;
2269 }
2270 }
2271 else
2272 {
2273 /* 64 bytes have been entered and there are still some remaining:
2274 Decrement buffer counter and set pointer to the proper
2275 memory location for the next data entering round.*/
2276 hhash->HashInCount -= 64U;
2277 hhash->pHashInBuffPtr += 64U;
2278 }
2279 }
2280 else
2281 {
2282 /* 64 or less bytes remain to be entered. This is the last
2283 data entering round. */
2284
2285 /* Get the buffer address */
2286 inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2287 /* Get the buffer counter */
2288 inputcounter = hhash->HashInCount;
2289 /* Disable Interrupts */
2290 __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
2291
2292 /* Write the Input block in the Data IN register */
2293 for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++)
2294 {
2295 HASH->DIN = *(uint32_t *)inputaddr;
2296 inputaddr += 4U;
2297 }
2298
2299 if (hhash->Accumulation == 1U)
2300 {
2301 /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
2302 The digest computation will be started when the last buffer data are entered. */
2303
2304 /* Reset multi buffers accumulation flag */
2305 hhash->Accumulation = 0U;
2306 /* Change the HASH state */
2307 hhash->State = HAL_HASH_STATE_READY;
2308 /* Call Input data transfer complete call back */
2309 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2310 hhash->InCpltCallback(hhash);
2311 #else
2312 HAL_HASH_InCpltCallback(hhash);
2313 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2314 }
2315 else
2316 {
2317 /* Start the Digest calculation */
2318 __HAL_HASH_START_DIGEST();
2319 /* Return indication that digest calculation has started:
2320 this return value triggers the call to Input data transfer
2321 complete call back as well as the proper transition from
2322 one step to another in HMAC mode. */
2323 ret = HASH_DIGEST_CALCULATION_STARTED;
2324 }
2325 /* Reset buffer counter */
2326 hhash->HashInCount = 0;
2327 }
2328
2329 /* Return whether or digest calculation has started */
2330 return ret;
2331 }
2332
2333 /**
2334 * @brief HMAC processing in polling mode.
2335 * @param hhash HASH handle.
2336 * @param Timeout Timeout value.
2337 * @retval HAL status
2338 */
HMAC_Processing(HASH_HandleTypeDef * hhash,uint32_t Timeout)2339 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
2340 {
2341 /* Ensure first that Phase is correct */
2342 if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2)
2343 && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3))
2344 {
2345 /* Change the HASH state */
2346 hhash->State = HAL_HASH_STATE_READY;
2347
2348 /* Process Unlock */
2349 __HAL_UNLOCK(hhash);
2350
2351 /* Return function status */
2352 return HAL_ERROR;
2353 }
2354
2355 /* HMAC Step 1 processing */
2356 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2357 {
2358 /************************** STEP 1 ******************************************/
2359 /* Configure the Number of valid bits in last word of the message */
2360 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2361
2362 /* Write input buffer in Data register */
2363 hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2364 if (hhash->Status != HAL_OK)
2365 {
2366 return hhash->Status;
2367 }
2368
2369 /* Check whether or not key entering process has been suspended */
2370 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2371 {
2372 /* Process Unlocked */
2373 __HAL_UNLOCK(hhash);
2374
2375 /* Stop right there and return function status */
2376 return HAL_OK;
2377 }
2378
2379 /* No processing suspension at this point: set DCAL bit. */
2380 __HAL_HASH_START_DIGEST();
2381
2382 /* Wait for BUSY flag to be cleared */
2383 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2384 {
2385 return HAL_TIMEOUT;
2386 }
2387
2388 /* Move from Step 1 to Step 2 */
2389 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
2390
2391 }
2392
2393 /* HMAC Step 2 processing.
2394 After phase check, HMAC_Processing() may
2395 - directly start up from this point in resumption case
2396 if the same Step 2 processing was suspended previously
2397 - or fall through from the Step 1 processing carried out hereabove */
2398 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2399 {
2400 /************************** STEP 2 ******************************************/
2401 /* Configure the Number of valid bits in last word of the message */
2402 __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
2403
2404 /* Write input buffer in Data register */
2405 hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
2406 if (hhash->Status != HAL_OK)
2407 {
2408 return hhash->Status;
2409 }
2410
2411 /* Check whether or not data entering process has been suspended */
2412 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2413 {
2414 /* Process Unlocked */
2415 __HAL_UNLOCK(hhash);
2416
2417 /* Stop right there and return function status */
2418 return HAL_OK;
2419 }
2420
2421 /* No processing suspension at this point: set DCAL bit. */
2422 __HAL_HASH_START_DIGEST();
2423
2424 /* Wait for BUSY flag to be cleared */
2425 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2426 {
2427 return HAL_TIMEOUT;
2428 }
2429
2430 /* Move from Step 2 to Step 3 */
2431 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
2432 /* In case Step 1 phase was suspended then resumed,
2433 set again Key input buffers and size before moving to
2434 next step */
2435 hhash->pHashKeyBuffPtr = hhash->Init.pKey;
2436 hhash->HashKeyCount = hhash->Init.KeySize;
2437 }
2438
2439
2440 /* HMAC Step 3 processing.
2441 After phase check, HMAC_Processing() may
2442 - directly start up from this point in resumption case
2443 if the same Step 3 processing was suspended previously
2444 - or fall through from the Step 2 processing carried out hereabove */
2445 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
2446 {
2447 /************************** STEP 3 ******************************************/
2448 /* Configure the Number of valid bits in last word of the message */
2449 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2450
2451 /* Write input buffer in Data register */
2452 hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2453 if (hhash->Status != HAL_OK)
2454 {
2455 return hhash->Status;
2456 }
2457
2458 /* Check whether or not key entering process has been suspended */
2459 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2460 {
2461 /* Process Unlocked */
2462 __HAL_UNLOCK(hhash);
2463
2464 /* Stop right there and return function status */
2465 return HAL_OK;
2466 }
2467
2468 /* No processing suspension at this point: start the Digest calculation. */
2469 __HAL_HASH_START_DIGEST();
2470
2471 /* Wait for DCIS flag to be set */
2472 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2473 {
2474 return HAL_TIMEOUT;
2475 }
2476
2477 /* Read the message digest */
2478 HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2479
2480 /* Reset HASH state machine */
2481 hhash->Phase = HAL_HASH_PHASE_READY;
2482 }
2483
2484 /* Change the HASH state */
2485 hhash->State = HAL_HASH_STATE_READY;
2486
2487 /* Process Unlock */
2488 __HAL_UNLOCK(hhash);
2489
2490 /* Return function status */
2491 return HAL_OK;
2492 }
2493
2494
2495 /**
2496 * @brief Initialize the HASH peripheral, next process pInBuffer then
2497 * read the computed digest.
2498 * @note Digest is available in pOutBuffer.
2499 * @param hhash HASH handle.
2500 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
2501 * @param Size length of the input buffer in bytes.
2502 * @param pOutBuffer pointer to the computed digest.
2503 * @param Timeout Timeout value.
2504 * @param Algorithm HASH algorithm.
2505 * @retval HAL status
2506 */
HASH_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)2507 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
2508 uint32_t Timeout, uint32_t Algorithm)
2509 {
2510 uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */
2511 uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
2512 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2513
2514
2515 /* Initiate HASH processing in case of start or resumption */
2516 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2517 {
2518 /* Check input parameters */
2519 if ((pInBuffer == NULL) || (pOutBuffer == NULL))
2520 {
2521 hhash->State = HAL_HASH_STATE_READY;
2522 return HAL_ERROR;
2523 }
2524
2525 /* Process Locked */
2526 __HAL_LOCK(hhash);
2527
2528 /* Check if initialization phase has not been already performed */
2529 if (hhash->Phase == HAL_HASH_PHASE_READY)
2530 {
2531 /* Change the HASH state */
2532 hhash->State = HAL_HASH_STATE_BUSY;
2533
2534 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2535 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2536
2537 /* Configure the number of valid bits in last word of the message */
2538 __HAL_HASH_SET_NBVALIDBITS(Size);
2539
2540 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2541 input parameters of HASH_WriteData() */
2542 pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */
2543 Size_tmp = Size; /* Size_tmp contains the input data size in bytes */
2544
2545 /* Set the phase */
2546 hhash->Phase = HAL_HASH_PHASE_PROCESS;
2547 }
2548 else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
2549 {
2550 /* if the Peripheral has already been initialized, two cases are possible */
2551
2552 /* Process resumption time ... */
2553 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2554 {
2555 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2556 to the API input parameters but to those saved beforehand by HASH_WriteData()
2557 when the processing was suspended */
2558 pInBuffer_tmp = hhash->pHashInBuffPtr;
2559 Size_tmp = hhash->HashInCount;
2560 }
2561 /* ... or multi-buffer HASH processing end */
2562 else
2563 {
2564 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2565 input parameters of HASH_WriteData() */
2566 pInBuffer_tmp = pInBuffer;
2567 Size_tmp = Size;
2568 /* Configure the number of valid bits in last word of the message */
2569 __HAL_HASH_SET_NBVALIDBITS(Size);
2570 }
2571 /* Change the HASH state */
2572 hhash->State = HAL_HASH_STATE_BUSY;
2573 }
2574 else
2575 {
2576 /* Phase error */
2577 hhash->State = HAL_HASH_STATE_READY;
2578
2579 /* Process Unlocked */
2580 __HAL_UNLOCK(hhash);
2581
2582 /* Return function status */
2583 return HAL_ERROR;
2584 }
2585
2586
2587 /* Write input buffer in Data register */
2588 hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2589 if (hhash->Status != HAL_OK)
2590 {
2591 return hhash->Status;
2592 }
2593
2594 /* If the process has not been suspended, carry on to digest calculation */
2595 if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2596 {
2597 /* Start the Digest calculation */
2598 __HAL_HASH_START_DIGEST();
2599
2600 /* Wait for DCIS flag to be set */
2601 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2602 {
2603 return HAL_TIMEOUT;
2604 }
2605
2606 /* Read the message digest */
2607 HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
2608
2609 /* Change the HASH state */
2610 hhash->State = HAL_HASH_STATE_READY;
2611
2612 /* Reset HASH state machine */
2613 hhash->Phase = HAL_HASH_PHASE_READY;
2614
2615 }
2616
2617 /* Process Unlocked */
2618 __HAL_UNLOCK(hhash);
2619
2620 /* Return function status */
2621 return HAL_OK;
2622
2623 }
2624 else
2625 {
2626 return HAL_BUSY;
2627 }
2628 }
2629
2630
2631 /**
2632 * @brief If not already done, initialize the HASH peripheral then
2633 * processes pInBuffer.
2634 * @note Field hhash->Phase of HASH handle is tested to check whether or not
2635 * the Peripheral has already been initialized.
2636 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2637 * HASH digest computation is corrupted.
2638 * @param hhash HASH handle.
2639 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
2640 * @param Size length of the input buffer in bytes, must be a multiple of 4.
2641 * @param Algorithm HASH algorithm.
2642 * @retval HAL status
2643 */
HASH_Accumulate(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)2644 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2645 {
2646 uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */
2647 uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
2648 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2649
2650 /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2651 if ((Size % 4U) != 0U)
2652 {
2653 return HAL_ERROR;
2654 }
2655
2656 /* Initiate HASH processing in case of start or resumption */
2657 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2658 {
2659 /* Check input parameters */
2660 if ((pInBuffer == NULL) || (Size == 0U))
2661 {
2662 hhash->State = HAL_HASH_STATE_READY;
2663 return HAL_ERROR;
2664 }
2665
2666 /* Process Locked */
2667 __HAL_LOCK(hhash);
2668
2669 /* If resuming the HASH processing */
2670 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2671 {
2672 /* Change the HASH state */
2673 hhash->State = HAL_HASH_STATE_BUSY;
2674
2675 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2676 to the API input parameters but to those saved beforehand by HASH_WriteData()
2677 when the processing was suspended */
2678 pInBuffer_tmp = hhash->pHashInBuffPtr; /* pInBuffer_tmp is set to the input data address */
2679 Size_tmp = hhash->HashInCount; /* Size_tmp contains the input data size in bytes */
2680
2681 }
2682 else
2683 {
2684 /* Change the HASH state */
2685 hhash->State = HAL_HASH_STATE_BUSY;
2686
2687 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2688 input parameters of HASH_WriteData() */
2689 pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */
2690 Size_tmp = Size; /* Size_tmp contains the input data size in bytes */
2691
2692 /* Check if initialization phase has already be performed */
2693 if (hhash->Phase == HAL_HASH_PHASE_READY)
2694 {
2695 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2696 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2697 }
2698
2699 /* Set the phase */
2700 hhash->Phase = HAL_HASH_PHASE_PROCESS;
2701
2702 }
2703
2704 /* Write input buffer in Data register */
2705 hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2706 if (hhash->Status != HAL_OK)
2707 {
2708 return hhash->Status;
2709 }
2710
2711 /* If the process has not been suspended, move the state to Ready */
2712 if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2713 {
2714 /* Change the HASH state */
2715 hhash->State = HAL_HASH_STATE_READY;
2716 }
2717
2718 /* Process Unlocked */
2719 __HAL_UNLOCK(hhash);
2720
2721 /* Return function status */
2722 return HAL_OK;
2723
2724 }
2725 else
2726 {
2727 return HAL_BUSY;
2728 }
2729
2730
2731 }
2732
2733
2734 /**
2735 * @brief If not already done, initialize the HASH peripheral then
2736 * processes pInBuffer in interruption mode.
2737 * @note Field hhash->Phase of HASH handle is tested to check whether or not
2738 * the Peripheral has already been initialized.
2739 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2740 * HASH digest computation is corrupted.
2741 * @param hhash HASH handle.
2742 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
2743 * @param Size length of the input buffer in bytes, must be a multiple of 4.
2744 * @param Algorithm HASH algorithm.
2745 * @retval HAL status
2746 */
HASH_Accumulate_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)2747 HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2748 {
2749 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2750 __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2751 uint32_t SizeVar = Size;
2752
2753 /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2754 if ((Size % 4U) != 0U)
2755 {
2756 return HAL_ERROR;
2757 }
2758
2759 /* Initiate HASH processing in case of start or resumption */
2760 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2761 {
2762 /* Check input parameters */
2763 if ((pInBuffer == NULL) || (Size == 0U))
2764 {
2765 hhash->State = HAL_HASH_STATE_READY;
2766 return HAL_ERROR;
2767 }
2768
2769 /* Process Locked */
2770 __HAL_LOCK(hhash);
2771
2772 /* If resuming the HASH processing */
2773 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2774 {
2775 /* Change the HASH state */
2776 hhash->State = HAL_HASH_STATE_BUSY;
2777 }
2778 else
2779 {
2780 /* Change the HASH state */
2781 hhash->State = HAL_HASH_STATE_BUSY;
2782
2783 /* Check if initialization phase has already be performed */
2784 if (hhash->Phase == HAL_HASH_PHASE_READY)
2785 {
2786 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2787 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2788 hhash->HashITCounter = 1;
2789 }
2790 else
2791 {
2792 hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2793 }
2794
2795 /* Set the phase */
2796 hhash->Phase = HAL_HASH_PHASE_PROCESS;
2797
2798 /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2799 fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2800 Therefore, first words are manually entered until DINIS raises, or until there
2801 is not more data to enter. */
2802 while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U))
2803 {
2804
2805 /* Write input data 4 bytes at a time */
2806 HASH->DIN = *(uint32_t *)inputaddr;
2807 inputaddr += 4U;
2808 SizeVar -= 4U;
2809 }
2810
2811 /* If DINIS is still not set or if all the data have been fed, stop here */
2812 if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U))
2813 {
2814 /* Change the HASH state */
2815 hhash->State = HAL_HASH_STATE_READY;
2816
2817 /* Process Unlock */
2818 __HAL_UNLOCK(hhash);
2819
2820 /* Return function status */
2821 return HAL_OK;
2822 }
2823
2824 /* otherwise, carry on in interrupt-mode */
2825 hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data
2826 to be fed to the Peripheral */
2827 hhash->pHashInBuffPtr = (uint8_t *)inputaddr; /* Points at data which will be fed to the Peripheral at
2828 the next interruption */
2829 /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2830 the information describing where the HASH process is stopped.
2831 These variables are used later on to resume the HASH processing at the
2832 correct location. */
2833
2834 }
2835
2836 /* Set multi buffers accumulation flag */
2837 hhash->Accumulation = 1U;
2838
2839 /* Process Unlock */
2840 __HAL_UNLOCK(hhash);
2841
2842 /* Enable Data Input interrupt */
2843 __HAL_HASH_ENABLE_IT(HASH_IT_DINI);
2844
2845 /* Return function status */
2846 return HAL_OK;
2847
2848 }
2849 else
2850 {
2851 return HAL_BUSY;
2852 }
2853
2854 }
2855
2856
2857
2858 /**
2859 * @brief Initialize the HASH peripheral, next process pInBuffer then
2860 * read the computed digest in interruption mode.
2861 * @note Digest is available in pOutBuffer.
2862 * @param hhash HASH handle.
2863 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
2864 * @param Size length of the input buffer in bytes.
2865 * @param pOutBuffer pointer to the computed digest.
2866 * @param Algorithm HASH algorithm.
2867 * @retval HAL status
2868 */
HASH_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)2869 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
2870 uint32_t Algorithm)
2871 {
2872 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2873 __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2874 uint32_t polling_step = 0U;
2875 uint32_t initialization_skipped = 0U;
2876 uint32_t SizeVar = Size;
2877
2878 /* If State is ready or suspended, start or resume IT-based HASH processing */
2879 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2880 {
2881 /* Check input parameters */
2882 if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
2883 {
2884 hhash->State = HAL_HASH_STATE_READY;
2885 return HAL_ERROR;
2886 }
2887
2888 /* Process Locked */
2889 __HAL_LOCK(hhash);
2890
2891 /* Change the HASH state */
2892 hhash->State = HAL_HASH_STATE_BUSY;
2893
2894 /* Initialize IT counter */
2895 hhash->HashITCounter = 1;
2896
2897 /* Check if initialization phase has already be performed */
2898 if (hhash->Phase == HAL_HASH_PHASE_READY)
2899 {
2900 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2901 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2902
2903 /* Configure the number of valid bits in last word of the message */
2904 __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2905
2906
2907 hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data
2908 to be fed to the Peripheral */
2909 hhash->pHashInBuffPtr = pInBuffer; /* Points at data which will be fed to the Peripheral at
2910 the next interruption */
2911 /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2912 the information describing where the HASH process is stopped.
2913 These variables are used later on to resume the HASH processing at the
2914 correct location. */
2915
2916 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
2917 }
2918 else
2919 {
2920 initialization_skipped = 1; /* info user later on in case of multi-buffer */
2921 }
2922
2923 /* Set the phase */
2924 hhash->Phase = HAL_HASH_PHASE_PROCESS;
2925
2926 /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2927 fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2928 Therefore, first words are manually entered until DINIS raises. */
2929 while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U))
2930 {
2931 polling_step = 1U; /* note that some words are entered before enabling the interrupt */
2932
2933 /* Write input data 4 bytes at a time */
2934 HASH->DIN = *(uint32_t *)inputaddr;
2935 inputaddr += 4U;
2936 SizeVar -= 4U;
2937 }
2938
2939 if (polling_step == 1U)
2940 {
2941 if (SizeVar == 0U)
2942 {
2943 /* If all the data have been entered at this point, it only remains to
2944 read the digest */
2945 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
2946
2947 /* Start the Digest calculation */
2948 __HAL_HASH_START_DIGEST();
2949 /* Process Unlock */
2950 __HAL_UNLOCK(hhash);
2951
2952 /* Enable Interrupts */
2953 __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2954
2955 /* Return function status */
2956 return HAL_OK;
2957 }
2958 else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2959 {
2960 /* It remains data to enter and the Peripheral is ready to trigger DINIE,
2961 carry on as usual.
2962 Update HashInCount and pHashInBuffPtr accordingly. */
2963 hhash->HashInCount = SizeVar;
2964 hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
2965 /* Update the configuration of the number of valid bits in last word of the message */
2966 __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2967 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
2968 if (initialization_skipped == 1U)
2969 {
2970 hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2971 }
2972 }
2973 else
2974 {
2975 /* DINIS is not set but it remains a few data to enter (not enough for a full word).
2976 Manually enter the last bytes before enabling DCIE. */
2977 __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2978 HASH->DIN = *(uint32_t *)inputaddr;
2979
2980 /* Start the Digest calculation */
2981 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
2982 __HAL_HASH_START_DIGEST();
2983 /* Process Unlock */
2984 __HAL_UNLOCK(hhash);
2985
2986 /* Enable Interrupts */
2987 __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2988
2989 /* Return function status */
2990 return HAL_OK;
2991 }
2992 } /* if (polling_step == 1) */
2993
2994
2995 /* Process Unlock */
2996 __HAL_UNLOCK(hhash);
2997
2998 /* Enable Interrupts */
2999 __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
3000
3001 /* Return function status */
3002 return HAL_OK;
3003 }
3004 else
3005 {
3006 return HAL_BUSY;
3007 }
3008
3009 }
3010
3011
3012 /**
3013 * @brief Initialize the HASH peripheral then initiate a DMA transfer
3014 * to feed the input buffer to the Peripheral.
3015 * @note If MDMAT bit is set before calling this function (multi-buffer
3016 * HASH processing case), the input buffer size (in bytes) must be
3017 * a multiple of 4 otherwise, the HASH digest computation is corrupted.
3018 * For the processing of the last buffer of the thread, MDMAT bit must
3019 * be reset and the buffer length (in bytes) doesn't have to be a
3020 * multiple of 4.
3021 * @param hhash HASH handle.
3022 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
3023 * @param Size length of the input buffer in bytes.
3024 * @param Algorithm HASH algorithm.
3025 * @retval HAL status
3026 */
HASH_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)3027 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
3028 {
3029 uint32_t inputaddr;
3030 uint32_t inputSize;
3031 HAL_StatusTypeDef status ;
3032 HAL_HASH_StateTypeDef State_tmp = hhash->State;
3033
3034 #if defined (HASH_CR_MDMAT)
3035 /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
3036 (case of multi-buffer HASH processing) */
3037 assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
3038 #endif /* MDMA defined*/
3039 /* If State is ready or suspended, start or resume polling-based HASH processing */
3040 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3041 {
3042 /* Check input parameters */
3043 if ((pInBuffer == NULL) || (Size == 0U) ||
3044 /* Check phase coherency. Phase must be
3045 either READY (fresh start)
3046 or PROCESS (multi-buffer HASH management) */
3047 ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
3048 {
3049 hhash->State = HAL_HASH_STATE_READY;
3050 return HAL_ERROR;
3051 }
3052
3053
3054 /* Process Locked */
3055 __HAL_LOCK(hhash);
3056
3057 /* If not a resumption case */
3058 if (hhash->State == HAL_HASH_STATE_READY)
3059 {
3060 /* Change the HASH state */
3061 hhash->State = HAL_HASH_STATE_BUSY;
3062
3063 /* Check if initialization phase has already been performed.
3064 If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
3065 API is processing a new input data message in case of multi-buffer HASH
3066 computation. */
3067 if (hhash->Phase == HAL_HASH_PHASE_READY)
3068 {
3069 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
3070 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
3071
3072 /* Set the phase */
3073 hhash->Phase = HAL_HASH_PHASE_PROCESS;
3074 }
3075
3076 /* Configure the Number of valid bits in last word of the message */
3077 __HAL_HASH_SET_NBVALIDBITS(Size);
3078
3079 inputaddr = (uint32_t)pInBuffer; /* DMA transfer start address */
3080 inputSize = Size; /* DMA transfer size (in bytes) */
3081
3082 /* In case of suspension request, save the starting parameters */
3083 hhash->pHashInBuffPtr = pInBuffer; /* DMA transfer start address */
3084 hhash->HashInCount = Size; /* DMA transfer size (in bytes) */
3085
3086 }
3087 /* If resumption case */
3088 else
3089 {
3090 /* Change the HASH state */
3091 hhash->State = HAL_HASH_STATE_BUSY;
3092
3093 /* Resumption case, inputaddr and inputSize are not set to the API input parameters
3094 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3095 processing was suspended */
3096 inputaddr = (uint32_t)hhash->pHashInBuffPtr; /* DMA transfer start address */
3097 inputSize = hhash->HashInCount; /* DMA transfer size (in bytes) */
3098
3099 }
3100
3101 /* Set the HASH DMA transfer complete callback */
3102 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3103 /* Set the DMA error callback */
3104 hhash->hdmain->XferErrorCallback = HASH_DMAError;
3105
3106 /* Store number of words already pushed to manage proper DMA processing suspension */
3107 hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3108
3109 /* Enable the DMA In DMA stream */
3110 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
3111 (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \
3112 (inputSize / 4U)));
3113
3114 /* Enable DMA requests */
3115 SET_BIT(HASH->CR, HASH_CR_DMAE);
3116
3117 /* Process Unlock */
3118 __HAL_UNLOCK(hhash);
3119
3120 /* Return function status */
3121 if (status != HAL_OK)
3122 {
3123 /* Update HASH state machine to error */
3124 hhash->State = HAL_HASH_STATE_ERROR;
3125 }
3126
3127 return status;
3128 }
3129 else
3130 {
3131 return HAL_BUSY;
3132 }
3133 }
3134
3135 /**
3136 * @brief Return the computed digest.
3137 * @note The API waits for DCIS to be set then reads the computed digest.
3138 * @param hhash HASH handle.
3139 * @param pOutBuffer pointer to the computed digest.
3140 * @param Timeout Timeout value.
3141 * @retval HAL status
3142 */
HASH_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)3143 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
3144 {
3145
3146 if (hhash->State == HAL_HASH_STATE_READY)
3147 {
3148 /* Check parameter */
3149 if (pOutBuffer == NULL)
3150 {
3151 return HAL_ERROR;
3152 }
3153
3154 /* Process Locked */
3155 __HAL_LOCK(hhash);
3156
3157 /* Change the HASH state to busy */
3158 hhash->State = HAL_HASH_STATE_BUSY;
3159
3160 /* Wait for DCIS flag to be set */
3161 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
3162 {
3163 return HAL_TIMEOUT;
3164 }
3165
3166 /* Read the message digest */
3167 HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
3168
3169 /* Change the HASH state to ready */
3170 hhash->State = HAL_HASH_STATE_READY;
3171
3172 /* Reset HASH state machine */
3173 hhash->Phase = HAL_HASH_PHASE_READY;
3174
3175 /* Process UnLock */
3176 __HAL_UNLOCK(hhash);
3177
3178 /* Return function status */
3179 return HAL_OK;
3180
3181 }
3182 else
3183 {
3184 return HAL_BUSY;
3185 }
3186
3187 }
3188
3189
3190 /**
3191 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3192 * read the computed digest.
3193 * @note Digest is available in pOutBuffer.
3194 * @note Same key is used for the inner and the outer hash functions; pointer to key and
3195 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3196 * @param hhash HASH handle.
3197 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
3198 * @param Size length of the input buffer in bytes.
3199 * @param pOutBuffer pointer to the computed digest.
3200 * @param Timeout Timeout value.
3201 * @param Algorithm HASH algorithm.
3202 * @retval HAL status
3203 */
HMAC_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)3204 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
3205 uint32_t Timeout, uint32_t Algorithm)
3206 {
3207 HAL_HASH_StateTypeDef State_tmp = hhash->State;
3208
3209 /* If State is ready or suspended, start or resume polling-based HASH processing */
3210 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3211 {
3212 /* Check input parameters */
3213 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3214 || (pOutBuffer == NULL))
3215 {
3216 hhash->State = HAL_HASH_STATE_READY;
3217 return HAL_ERROR;
3218 }
3219
3220 /* Process Locked */
3221 __HAL_LOCK(hhash);
3222
3223 /* Change the HASH state */
3224 hhash->State = HAL_HASH_STATE_BUSY;
3225
3226 /* Check if initialization phase has already be performed */
3227 if (hhash->Phase == HAL_HASH_PHASE_READY)
3228 {
3229 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3230 if (hhash->Init.KeySize > 64U)
3231 {
3232 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3233 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3234 }
3235 else
3236 {
3237 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3238 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3239 }
3240 /* Set the phase to Step 1 */
3241 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3242 /* Resort to hhash internal fields to feed the Peripheral.
3243 Parameters will be updated in case of suspension to contain the proper
3244 information at resumption time. */
3245 hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */
3246 hhash->pHashInBuffPtr = pInBuffer; /* Input data address, HMAC_Processing input
3247 parameter for Step 2 */
3248 hhash->HashInCount = Size; /* Input data size, HMAC_Processing input
3249 parameter for Step 2 */
3250 hhash->HashBuffSize = Size; /* Store the input buffer size for the whole HMAC process*/
3251 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address, HMAC_Processing input parameter for Step
3252 1 and Step 3 */
3253 hhash->HashKeyCount = hhash->Init.KeySize; /* Key size, HMAC_Processing input parameter for Step 1
3254 and Step 3 */
3255 }
3256
3257 /* Carry out HMAC processing */
3258 return HMAC_Processing(hhash, Timeout);
3259
3260 }
3261 else
3262 {
3263 return HAL_BUSY;
3264 }
3265 }
3266
3267
3268
3269 /**
3270 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3271 * read the computed digest in interruption mode.
3272 * @note Digest is available in pOutBuffer.
3273 * @note Same key is used for the inner and the outer hash functions; pointer to key and
3274 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3275 * @param hhash HASH handle.
3276 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
3277 * @param Size length of the input buffer in bytes.
3278 * @param pOutBuffer pointer to the computed digest.
3279 * @param Algorithm HASH algorithm.
3280 * @retval HAL status
3281 */
HMAC_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)3282 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
3283 uint32_t Algorithm)
3284 {
3285 HAL_HASH_StateTypeDef State_tmp = hhash->State;
3286
3287 /* If State is ready or suspended, start or resume IT-based HASH processing */
3288 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3289 {
3290 /* Check input parameters */
3291 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3292 || (pOutBuffer == NULL))
3293 {
3294 hhash->State = HAL_HASH_STATE_READY;
3295 return HAL_ERROR;
3296 }
3297
3298 /* Process Locked */
3299 __HAL_LOCK(hhash);
3300
3301 /* Change the HASH state */
3302 hhash->State = HAL_HASH_STATE_BUSY;
3303
3304 /* Initialize IT counter */
3305 hhash->HashITCounter = 1;
3306
3307 /* Check if initialization phase has already be performed */
3308 if (hhash->Phase == HAL_HASH_PHASE_READY)
3309 {
3310 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3311 if (hhash->Init.KeySize > 64U)
3312 {
3313 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3314 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3315 }
3316 else
3317 {
3318 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3319 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3320 }
3321
3322 /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
3323 to feed the Peripheral whatever the HMAC step.
3324 Lines below are set to start HMAC Step 1 processing where key is entered first. */
3325 hhash->HashInCount = hhash->Init.KeySize; /* Key size */
3326 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* Key address */
3327
3328 /* Store input and output parameters in handle fields to manage steps transition
3329 or possible HMAC suspension/resumption */
3330 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */
3331 hhash->pHashMsgBuffPtr = pInBuffer; /* Input message address */
3332 hhash->HashBuffSize = Size; /* Input message size (in bytes) */
3333 hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */
3334
3335 /* Configure the number of valid bits in last word of the key */
3336 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3337
3338 /* Set the phase to Step 1 */
3339 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3340 }
3341 else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
3342 {
3343 /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
3344
3345 }
3346 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3347 {
3348 /* Restart IT-based HASH processing after Step 2 suspension */
3349
3350 }
3351 else
3352 {
3353 /* Error report as phase incorrect */
3354 /* Process Unlock */
3355 __HAL_UNLOCK(hhash);
3356 hhash->State = HAL_HASH_STATE_READY;
3357 return HAL_ERROR;
3358 }
3359
3360 /* Process Unlock */
3361 __HAL_UNLOCK(hhash);
3362
3363 /* Enable Interrupts */
3364 __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
3365
3366 /* Return function status */
3367 return HAL_OK;
3368 }
3369 else
3370 {
3371 return HAL_BUSY;
3372 }
3373
3374 }
3375
3376
3377
3378 /**
3379 * @brief Initialize the HASH peripheral in HMAC mode then initiate the required
3380 * DMA transfers to feed the key and the input buffer to the Peripheral.
3381 * @note Same key is used for the inner and the outer hash functions; pointer to key and
3382 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3383 * @note In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
3384 * be a multiple of 4 otherwise, the HASH digest computation is corrupted.
3385 * Only the length of the last buffer of the thread doesn't have to be a
3386 * multiple of 4.
3387 * @param hhash HASH handle.
3388 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
3389 * @param Size length of the input buffer in bytes.
3390 * @param Algorithm HASH algorithm.
3391 * @retval HAL status
3392 */
HMAC_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)3393 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
3394 {
3395 uint32_t inputaddr;
3396 uint32_t inputSize;
3397 HAL_StatusTypeDef status ;
3398 HAL_HASH_StateTypeDef State_tmp = hhash->State;
3399 /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
3400 is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
3401 assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size));
3402 /* If State is ready or suspended, start or resume DMA-based HASH processing */
3403 if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3404 {
3405 /* Check input parameters */
3406 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) ||
3407 /* Check phase coherency. Phase must be
3408 either READY (fresh start)
3409 or one of HMAC PROCESS steps (multi-buffer HASH management) */
3410 ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
3411 {
3412 hhash->State = HAL_HASH_STATE_READY;
3413 return HAL_ERROR;
3414 }
3415
3416
3417 /* Process Locked */
3418 __HAL_LOCK(hhash);
3419
3420 /* If not a case of resumption after suspension */
3421 if (hhash->State == HAL_HASH_STATE_READY)
3422 {
3423 /* Check whether or not initialization phase has already be performed */
3424 if (hhash->Phase == HAL_HASH_PHASE_READY)
3425 {
3426 /* Change the HASH state */
3427 hhash->State = HAL_HASH_STATE_BUSY;
3428 #if defined(HASH_CR_MDMAT)
3429 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
3430 At the same time, ensure MDMAT bit is cleared. */
3431 if (hhash->Init.KeySize > 64U)
3432 {
3433 MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3434 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3435 }
3436 else
3437 {
3438 MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3439 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3440 }
3441 #else
3442 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3443 if (hhash->Init.KeySize > 64U)
3444 {
3445 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3446 Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3447 }
3448 else
3449 {
3450 MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3451 Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3452 }
3453 #endif /* HASH_CR_MDMAT*/
3454 /* Store input aparameters in handle fields to manage steps transition
3455 or possible HMAC suspension/resumption */
3456 hhash->HashInCount = hhash->Init.KeySize; /* Initial size for first DMA transfer (key size) */
3457 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */
3458 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
3459 hhash->pHashMsgBuffPtr = pInBuffer; /* Input data address */
3460 hhash->HashBuffSize = Size; /* input data size (in bytes) */
3461
3462 /* Set DMA input parameters */
3463 inputaddr = (uint32_t)(hhash->Init.pKey); /* Address passed to DMA (start by entering Key message) */
3464 inputSize = hhash->Init.KeySize; /* Size for first DMA transfer (in bytes) */
3465
3466 /* Configure the number of valid bits in last word of the key */
3467 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3468
3469 /* Set the phase to Step 1 */
3470 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3471
3472 }
3473 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3474 {
3475 /* Process a new input data message in case of multi-buffer HMAC processing
3476 (this is not a resumption case) */
3477
3478 /* Change the HASH state */
3479 hhash->State = HAL_HASH_STATE_BUSY;
3480
3481 /* Save input parameters to be able to manage possible suspension/resumption */
3482 hhash->HashInCount = Size; /* Input message address */
3483 hhash->pHashInBuffPtr = pInBuffer; /* Input message size in bytes */
3484
3485 /* Set DMA input parameters */
3486 inputaddr = (uint32_t)pInBuffer; /* Input message address */
3487 inputSize = Size; /* Input message size in bytes */
3488
3489 if (hhash->DigestCalculationDisable == RESET)
3490 {
3491 /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
3492 #if defined(HASH_CR_MDMAT)
3493 __HAL_HASH_RESET_MDMAT();
3494 #endif /* HASH_CR_MDMAT*/
3495 __HAL_HASH_SET_NBVALIDBITS(inputSize);
3496 }
3497 }
3498 else
3499 {
3500 /* Phase not aligned with handle READY state */
3501 __HAL_UNLOCK(hhash);
3502 /* Return function status */
3503 return HAL_ERROR;
3504 }
3505 }
3506 else
3507 {
3508 /* Resumption case (phase may be Step 1, 2 or 3) */
3509
3510 /* Change the HASH state */
3511 hhash->State = HAL_HASH_STATE_BUSY;
3512
3513 /* Set DMA input parameters at resumption location;
3514 inputaddr and inputSize are not set to the API input parameters
3515 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3516 processing was suspended. */
3517 inputaddr = (uint32_t)(hhash->pHashInBuffPtr); /* Input message address */
3518 inputSize = hhash->HashInCount; /* Input message size in bytes */
3519 }
3520
3521
3522 /* Set the HASH DMA transfer complete callback */
3523 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3524 /* Set the DMA error callback */
3525 hhash->hdmain->XferErrorCallback = HASH_DMAError;
3526
3527 /* Store number of words already pushed to manage proper DMA processing suspension */
3528 hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3529
3530 /* Enable the DMA In DMA stream */
3531 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
3532 (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \
3533 : (inputSize / 4U)));
3534
3535 /* Enable DMA requests */
3536 SET_BIT(HASH->CR, HASH_CR_DMAE);
3537
3538 /* Process Unlocked */
3539 __HAL_UNLOCK(hhash);
3540
3541 /* Return function status */
3542 if (status != HAL_OK)
3543 {
3544 /* Update HASH state machine to error */
3545 hhash->State = HAL_HASH_STATE_ERROR;
3546 }
3547
3548 /* Return function status */
3549 return status;
3550 }
3551 else
3552 {
3553 return HAL_BUSY;
3554 }
3555 }
3556 /**
3557 * @}
3558 */
3559
3560 #endif /* HAL_HASH_MODULE_ENABLED */
3561
3562 /**
3563 * @}
3564 */
3565 #endif /* HASH*/
3566 /**
3567 * @}
3568 */
3569
3570