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