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