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