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