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