2 ******************************************************************************
3 * @file stm32h7xx_hal_hash.c
4 * @author MCD Application Team
5 * @brief HASH HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the HASH peripheral:
8 * + Initialization and de-initialization methods
9 * + HASH or HMAC processing in polling mode
10 * + HASH or HMAC processing in interrupt mode
11 * + HASH or HMAC processing in DMA mode
12 * + Peripheral State methods
13 * + HASH or HMAC processing suspension/resumption
16 ===============================================================================
17 ##### How to use this driver #####
18 ===============================================================================
20 The HASH HAL driver can be used as follows:
22 (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit():
23 (##) Enable the HASH interface clock using __HASH_CLK_ENABLE()
24 (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT())
25 (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority()
26 (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ()
27 (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API
28 (##) When resorting to DMA-based APIs (e.g. HAL_HASH_xxx_Start_DMA())
29 (+++) Enable the DMAx interface clock using
31 (+++) Configure and enable one DMA stream to manage data transfer from
32 memory to peripheral (input stream). Managing data transfer from
33 peripheral to memory can be performed only using CPU.
34 (+++) Associate the initialized DMA handle to the HASH DMA handle
36 (+++) Configure the priority and enable the NVIC for the transfer complete
37 interrupt on the DMA Stream: use
38 HAL_NVIC_SetPriority() and
41 (#)Initialize the HASH HAL using HAL_HASH_Init(). This function:
42 (##) resorts to HAL_HASH_MspInit() for low-level initialization,
43 (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit.
45 (#)Three processing schemes are available:
46 (##) Polling mode: processing APIs are blocking functions
47 i.e. they process the data and wait till the digest computation is finished,
48 e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC
49 (##) Interrupt mode: processing APIs are not blocking functions
50 i.e. they process the data under interrupt,
51 e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC
52 (##) DMA mode: processing APIs are not blocking functions and the CPU is
53 not used for data transfer i.e. the data transfer is ensured by DMA,
54 e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA()
55 for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish()
56 is then required to retrieve the digest.
58 (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is
59 initialized and processes the buffer fed in input. When the input data have all been
60 fed to the Peripheral, the digest computation can start.
62 (#)Multi-buffer processing is possible in polling, interrupt and DMA modes.
63 (##) In polling mode, only multi-buffer HASH processing is possible.
64 API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one.
65 User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as
66 well the computed digest.
68 (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer,
69 except for the last one.
70 User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as
71 well the computed digest.
73 (##) In DMA mode, multi-buffer HASH and HMAC processing are possible.
74 (+++) HASH processing: once initialization is done, MDMAT bit must be set thru __HAL_HASH_SET_MDMAT() macro.
75 From that point, each buffer can be fed to the Peripheral thru HAL_HASH_xxx_Start_DMA() API.
76 Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT()
77 macro then wrap-up the HASH processing in feeding the last input buffer thru the
78 same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to
79 API HAL_HASH_xxx_Finish().
80 (+++) HMAC processing (requires to resort to extended functions):
81 after initialization, the key and the first input buffer are entered
82 in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
84 The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this
85 point, the HMAC processing is still carrying out step 2.
86 Then, step 2 for the last input buffer and step 3 are carried out by a single call
87 to HAL_HMACEx_xxx_Step2_3_DMA().
89 The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish().
93 (##) Two APIs are available to suspend HASH or HMAC processing:
94 (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode),
95 (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA.
97 (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows
98 to save in memory the Peripheral context. This context can be restored afterwards
99 to resume the HASH processing thanks to HAL_HASH_ContextRestoring().
101 (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension
102 time, processing can be restarted with the same API call (same API, same handle,
103 same parameters) as done before the suspension. Relevant parameters to restart at
104 the proper location are internally saved in the HASH handle.
106 (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
108 *** Remarks on message length ***
109 ===================================
111 (#) HAL in interruption mode (interruptions driven)
113 (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes.
114 This is why, for driver implementation simplicity’s sake, user is requested to enter a message the
115 length of which is a multiple of 4 bytes.
117 (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR
118 to specify which bits to discard at the end of the complete message to process only the message bits
121 (##) If user needs to perform a hash computation of a large input buffer that is spread around various places
122 in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it
123 becomes necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral.
124 It is advised to the user to
125 (+++) achieve the first formatting operation by software then enter the data
126 (+++) while the Peripheral is processing the first input set, carry out the second formatting operation by software, to be ready when DINIS occurs.
127 (+++) repeat step 2 until the whole message is processed.
132 (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis.
133 The same field described above in HASH_STR is used to specify which bits to discard at the end of the DMA transfer
134 to process only the message bits and not extra bits. Due to hardware implementation, this is possible only at the
135 end of the complete message. When several DMA transfers are needed to enter the message, this is not applicable at
136 the end of the intermediary transfers.
138 (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive chunks of data
139 by software while the DMA transfer and processing is on-going for the first parts of the message. Due to the 32-bit alignment
140 required for the DMA transfer, it is underlined that the software formatting operation is more complex than in the IT mode.
142 *** Callback registration ***
143 ===================================
145 (#) The compilation define USE_HAL_HASH_REGISTER_CALLBACKS when set to 1
146 allows the user to configure dynamically the driver callbacks.
147 Use function @ref HAL_HASH_RegisterCallback() to register a user callback.
149 (#) Function @ref HAL_HASH_RegisterCallback() allows to register following callbacks:
150 (+) InCpltCallback : callback for input completion.
151 (+) DgstCpltCallback : callback for digest computation completion.
152 (+) ErrorCallback : callback for error.
153 (+) MspInitCallback : HASH MspInit.
154 (+) MspDeInitCallback : HASH MspDeInit.
155 This function takes as parameters the HAL peripheral handle, the Callback ID
156 and a pointer to the user callback function.
158 (#) Use function @ref HAL_HASH_UnRegisterCallback() to reset a callback to the default
159 weak (surcharged) function.
160 @ref HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle,
162 This function allows to reset following callbacks:
163 (+) InCpltCallback : callback for input completion.
164 (+) DgstCpltCallback : callback for digest computation completion.
165 (+) ErrorCallback : callback for error.
166 (+) MspInitCallback : HASH MspInit.
167 (+) MspDeInitCallback : HASH MspDeInit.
169 (#) By default, after the @ref HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET
170 all callbacks are reset to the corresponding legacy weak (surcharged) functions:
171 examples @ref HAL_HASH_InCpltCallback(), @ref HAL_HASH_DgstCpltCallback()
172 Exception done for MspInit and MspDeInit callbacks that are respectively
173 reset to the legacy weak (surcharged) functions in the @ref HAL_HASH_Init
174 and @ref HAL_HASH_DeInit only when these callbacks are null (not registered beforehand)
175 If not, MspInit or MspDeInit are not null, the @ref HAL_HASH_Init and @ref HAL_HASH_DeInit
176 keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
178 Callbacks can be registered/unregistered in READY state only.
179 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
180 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
181 during the Init/DeInit.
182 In that case first register the MspInit/MspDeInit user callbacks
183 using @ref HAL_HASH_RegisterCallback before calling @ref HAL_HASH_DeInit
184 or @ref HAL_HASH_Init function.
186 When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or
187 not defined, the callback registering feature is not available
188 and weak (surcharged) callbacks are used.
191 ******************************************************************************
194 * <h2><center>© Copyright (c) 2017 STMicroelectronics.
195 * All rights reserved.</center></h2>
197 * This software component is licensed by ST under BSD 3-Clause license,
198 * the "License"; You may not use this file except in compliance with the
199 * License. You may obtain a copy of the License at:
200 * opensource.org/licenses/BSD-3-Clause
202 ******************************************************************************
205 /* Includes ------------------------------------------------------------------*/
206 #include "stm32h7xx_hal.h"
209 /** @addtogroup STM32H7xx_HAL_Driver
214 /** @defgroup HASH HASH
215 * @brief HASH HAL module driver.
219 #ifdef HAL_HASH_MODULE_ENABLED
221 /* Private typedef -----------------------------------------------------------*/
222 /* Private define ------------------------------------------------------------*/
223 /** @defgroup HASH_Private_Constants HASH Private Constants
227 /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status
230 #define HASH_DIGEST_CALCULATION_NOT_STARTED ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */
231 #define HASH_DIGEST_CALCULATION_STARTED ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register */
236 /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers
239 #define HASH_NUMBER_OF_CSR_REGISTERS 54U /*!< Number of Context Swap Registers */
244 /** @defgroup HASH_TimeOut_Value HASH TimeOut Value
247 #define HASH_TIMEOUTVALUE 1000U /*!< Time-out value */
252 /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit
255 #define HASH_DMA_SUSPENSION_WORDS_LIMIT 20U /*!< Number of words below which DMA suspension is aborted */
264 /* Private macro -------------------------------------------------------------*/
265 /* Private variables ---------------------------------------------------------*/
266 /* Private function prototypes -----------------------------------------------*/
267 /** @defgroup HASH_Private_Functions HASH Private Functions
270 static void HASH_DMAXferCplt(DMA_HandleTypeDef
*hdma
);
271 static void HASH_DMAError(DMA_HandleTypeDef
*hdma
);
272 static void HASH_GetDigest(uint8_t *pMsgDigest
, uint8_t Size
);
273 static HAL_StatusTypeDef
HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef
*hhash
, uint32_t Flag
, FlagStatus Status
, uint32_t Timeout
);
274 static HAL_StatusTypeDef
HASH_WriteData(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
);
275 static HAL_StatusTypeDef
HASH_IT(HASH_HandleTypeDef
*hhash
);
276 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef
*hhash
);
277 static HAL_StatusTypeDef
HMAC_Processing(HASH_HandleTypeDef
*hhash
, uint32_t Timeout
);
282 /** @defgroup HASH_Exported_Functions HASH Exported Functions
286 /** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions
287 * @brief Initialization, configuration and call-back functions.
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
300 [..] This section provides as well call back functions definitions for user
302 (+) Input data transfer to Peripheral completion
303 (+) Calculated digest retrieval completion
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 * @note MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for
318 * multi-buffer HASH processing, user needs to resort to
319 * __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the
320 * relevant APIs manage themselves the MDMAT bit.
321 * @param hhash HASH handle
324 HAL_StatusTypeDef
HAL_HASH_Init(HASH_HandleTypeDef
*hhash
)
326 /* Check the hash handle allocation */
332 /* Check the parameters */
333 assert_param(IS_HASH_DATATYPE(hhash
->Init
.DataType
));
335 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
336 if (hhash
->State
== HAL_HASH_STATE_RESET
)
338 /* Allocate lock resource and initialize it */
339 hhash
->Lock
= HAL_UNLOCKED
;
341 /* Reset Callback pointers in HAL_HASH_STATE_RESET only */
342 hhash
->InCpltCallback
= HAL_HASH_InCpltCallback
; /* Legacy weak (surcharged) input completion callback */
343 hhash
->DgstCpltCallback
= HAL_HASH_DgstCpltCallback
; /* Legacy weak (surcharged) digest computation completion callback */
344 hhash
->ErrorCallback
= HAL_HASH_ErrorCallback
; /* Legacy weak (surcharged) error callback */
345 if(hhash
->MspInitCallback
== NULL
)
347 hhash
->MspInitCallback
= HAL_HASH_MspInit
;
350 /* Init the low level hardware */
351 hhash
->MspInitCallback(hhash
);
354 if(hhash
->State
== HAL_HASH_STATE_RESET
)
356 /* Allocate lock resource and initialize it */
357 hhash
->Lock
= HAL_UNLOCKED
;
359 /* Init the low level hardware */
360 HAL_HASH_MspInit(hhash
);
362 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
364 /* Change the HASH state */
365 hhash
->State
= HAL_HASH_STATE_BUSY
;
367 /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */
368 hhash
->HashInCount
= 0;
369 hhash
->HashBuffSize
= 0;
370 hhash
->HashITCounter
= 0;
371 hhash
->NbWordsAlreadyPushed
= 0;
372 /* Reset digest calculation bridle (MDMAT bit control) */
373 hhash
->DigestCalculationDisable
= RESET
;
374 /* Set phase to READY */
375 hhash
->Phase
= HAL_HASH_PHASE_READY
;
376 /* Reset suspension request flag */
377 hhash
->SuspendRequest
= HAL_HASH_SUSPEND_NONE
;
379 /* Set the data type bit */
380 MODIFY_REG(HASH
->CR
, HASH_CR_DATATYPE
, hhash
->Init
.DataType
);
381 /* Reset MDMAT bit */
382 __HAL_HASH_RESET_MDMAT();
383 /* Reset HASH handle status */
384 hhash
->Status
= HAL_OK
;
386 /* Set the HASH state to Ready */
387 hhash
->State
= HAL_HASH_STATE_READY
;
389 /* Initialise the error code */
390 hhash
->ErrorCode
= HAL_HASH_ERROR_NONE
;
392 /* Return function status */
397 * @brief DeInitialize the HASH peripheral.
398 * @param hhash HASH handle.
401 HAL_StatusTypeDef
HAL_HASH_DeInit(HASH_HandleTypeDef
*hhash
)
403 /* Check the HASH handle allocation */
409 /* Change the HASH state */
410 hhash
->State
= HAL_HASH_STATE_BUSY
;
412 /* Set the default HASH phase */
413 hhash
->Phase
= HAL_HASH_PHASE_READY
;
415 /* Reset HashInCount, HashITCounter and HashBuffSize */
416 hhash
->HashInCount
= 0;
417 hhash
->HashBuffSize
= 0;
418 hhash
->HashITCounter
= 0;
419 /* Reset digest calculation bridle (MDMAT bit control) */
420 hhash
->DigestCalculationDisable
= RESET
;
422 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
423 if(hhash
->MspDeInitCallback
== NULL
)
425 hhash
->MspDeInitCallback
= HAL_HASH_MspDeInit
;
428 /* DeInit the low level hardware */
429 hhash
->MspDeInitCallback(hhash
);
431 /* DeInit the low level hardware: CLOCK, NVIC */
432 HAL_HASH_MspDeInit(hhash
);
433 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
436 /* Reset HASH handle status */
437 hhash
->Status
= HAL_OK
;
439 /* Set the HASH state to Ready */
440 hhash
->State
= HAL_HASH_STATE_RESET
;
442 /* Initialise the error code */
443 hhash
->ErrorCode
= HAL_HASH_ERROR_NONE
;
445 /* Reset multi buffers accumulation flag */
446 hhash
->Accumulation
= 0U;
448 /* Return function status */
453 * @brief Initialize the HASH MSP.
454 * @param hhash HASH handle.
457 __weak
void HAL_HASH_MspInit(HASH_HandleTypeDef
*hhash
)
459 /* Prevent unused argument(s) compilation warning */
462 /* NOTE : This function should not be modified; when the callback is needed,
463 HAL_HASH_MspInit() can be implemented in the user file.
468 * @brief DeInitialize the HASH MSP.
469 * @param hhash HASH handle.
472 __weak
void HAL_HASH_MspDeInit(HASH_HandleTypeDef
*hhash
)
474 /* Prevent unused argument(s) compilation warning */
477 /* NOTE : This function should not be modified; when the callback is needed,
478 HAL_HASH_MspDeInit() can be implemented in the user file.
483 * @brief Input data transfer complete call back.
484 * @note HAL_HASH_InCpltCallback() is called when the complete input message
485 * has been fed to the Peripheral. This API is invoked only when input data are
486 * entered under interruption or thru DMA.
487 * @note In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set),
488 * HAL_HASH_InCpltCallback() is called at the end of each buffer feeding
490 * @param hhash HASH handle.
493 __weak
void HAL_HASH_InCpltCallback(HASH_HandleTypeDef
*hhash
)
495 /* Prevent unused argument(s) compilation warning */
498 /* NOTE : This function should not be modified; when the callback is needed,
499 HAL_HASH_InCpltCallback() can be implemented in the user file.
504 * @brief Digest computation complete call back.
505 * @note HAL_HASH_DgstCpltCallback() is used under interruption, is not
507 * @param hhash HASH handle.
510 __weak
void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef
*hhash
)
512 /* Prevent unused argument(s) compilation warning */
515 /* NOTE : This function should not be modified; when the callback is needed,
516 HAL_HASH_DgstCpltCallback() can be implemented in the user file.
521 * @brief Error callback.
522 * @note Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...)
523 * to retrieve the error type.
524 * @param hhash HASH handle.
527 __weak
void HAL_HASH_ErrorCallback(HASH_HandleTypeDef
*hhash
)
529 /* Prevent unused argument(s) compilation warning */
532 /* NOTE : This function should not be modified; when the callback is needed,
533 HAL_HASH_ErrorCallback() can be implemented in the user file.
537 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
539 * @brief Register a User HASH Callback
540 * To be used instead of the weak (surcharged) predefined callback
541 * @param hhash HASH handle
542 * @param CallbackID ID of the callback to be registered
543 * This parameter can be one of the following values:
544 * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
545 * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
546 * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
547 * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
548 * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
549 * @param pCallback pointer to the Callback function
552 HAL_StatusTypeDef
HAL_HASH_RegisterCallback(HASH_HandleTypeDef
*hhash
, HAL_HASH_CallbackIDTypeDef CallbackID
, pHASH_CallbackTypeDef pCallback
)
554 HAL_StatusTypeDef status
= HAL_OK
;
556 if(pCallback
== NULL
)
558 /* Update the error code */
559 hhash
->ErrorCode
|= HAL_HASH_ERROR_INVALID_CALLBACK
;
565 if(HAL_HASH_STATE_READY
== hhash
->State
)
569 case HAL_HASH_INPUTCPLT_CB_ID
:
570 hhash
->InCpltCallback
= pCallback
;
573 case HAL_HASH_DGSTCPLT_CB_ID
:
574 hhash
->DgstCpltCallback
= pCallback
;
577 case HAL_HASH_ERROR_CB_ID
:
578 hhash
->ErrorCallback
= pCallback
;
581 case HAL_HASH_MSPINIT_CB_ID
:
582 hhash
->MspInitCallback
= pCallback
;
585 case HAL_HASH_MSPDEINIT_CB_ID
:
586 hhash
->MspDeInitCallback
= pCallback
;
590 /* Update the error code */
591 hhash
->ErrorCode
|= HAL_HASH_ERROR_INVALID_CALLBACK
;
592 /* update return status */
597 else if(HAL_HASH_STATE_RESET
== hhash
->State
)
601 case HAL_HASH_MSPINIT_CB_ID
:
602 hhash
->MspInitCallback
= pCallback
;
605 case HAL_HASH_MSPDEINIT_CB_ID
:
606 hhash
->MspDeInitCallback
= pCallback
;
610 /* Update the error code */
611 hhash
->ErrorCode
|= HAL_HASH_ERROR_INVALID_CALLBACK
;
612 /* update return status */
619 /* Update the error code */
620 hhash
->ErrorCode
|= HAL_HASH_ERROR_INVALID_CALLBACK
;
621 /* update return status */
631 * @brief Unregister a HASH Callback
632 * HASH Callback is redirected to the weak (surcharged) predefined callback
633 * @param hhash HASH handle
634 * @param CallbackID ID of the callback to be unregistered
635 * This parameter can be one of the following values:
636 * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
637 * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
638 * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
639 * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
640 * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
643 HAL_StatusTypeDef
HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef
*hhash
, HAL_HASH_CallbackIDTypeDef CallbackID
)
645 HAL_StatusTypeDef status
= HAL_OK
;
650 if(HAL_HASH_STATE_READY
== hhash
->State
)
654 case HAL_HASH_INPUTCPLT_CB_ID
:
655 hhash
->InCpltCallback
= HAL_HASH_InCpltCallback
; /* Legacy weak (surcharged) input completion callback */
658 case HAL_HASH_DGSTCPLT_CB_ID
:
659 hhash
->DgstCpltCallback
= HAL_HASH_DgstCpltCallback
; /* Legacy weak (surcharged) digest computation completion callback */
662 case HAL_HASH_ERROR_CB_ID
:
663 hhash
->ErrorCallback
= HAL_HASH_ErrorCallback
; /* Legacy weak (surcharged) error callback */
666 case HAL_HASH_MSPINIT_CB_ID
:
667 hhash
->MspInitCallback
= HAL_HASH_MspInit
; /* Legacy weak (surcharged) Msp Init */
670 case HAL_HASH_MSPDEINIT_CB_ID
:
671 hhash
->MspDeInitCallback
= HAL_HASH_MspDeInit
; /* Legacy weak (surcharged) Msp DeInit */
675 /* Update the error code */
676 hhash
->ErrorCode
|= HAL_HASH_ERROR_INVALID_CALLBACK
;
677 /* update return status */
682 else if(HAL_HASH_STATE_RESET
== hhash
->State
)
686 case HAL_HASH_MSPINIT_CB_ID
:
687 hhash
->MspInitCallback
= HAL_HASH_MspInit
; /* Legacy weak (surcharged) Msp Init */
690 case HAL_HASH_MSPDEINIT_CB_ID
:
691 hhash
->MspDeInitCallback
= HAL_HASH_MspDeInit
; /* Legacy weak (surcharged) Msp DeInit */
695 /* Update the error code */
696 hhash
->ErrorCode
|= HAL_HASH_ERROR_INVALID_CALLBACK
;
697 /* update return status */
704 /* Update the error code */
705 hhash
->ErrorCode
|= HAL_HASH_ERROR_INVALID_CALLBACK
;
706 /* update return status */
714 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
720 /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode
721 * @brief HASH processing functions using polling mode.
724 ===============================================================================
725 ##### Polling mode HASH processing functions #####
726 ===============================================================================
727 [..] This section provides functions allowing to calculate in polling mode
728 the hash value using one of the following algorithms:
730 (++) HAL_HASH_MD5_Start()
731 (++) HAL_HASH_MD5_Accmlt()
732 (++) HAL_HASH_MD5_Accmlt_End()
734 (++) HAL_HASH_SHA1_Start()
735 (++) HAL_HASH_SHA1_Accmlt()
736 (++) HAL_HASH_SHA1_Accmlt_End()
738 [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
740 [..] In case of multi-buffer HASH processing (a single digest is computed while
741 several buffers are fed to the Peripheral), the user can resort to successive calls
742 to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call
743 to HAL_HASH_xxx_Accumulate_End().
750 * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
751 * read the computed digest.
752 * @note Digest is available in pOutBuffer.
753 * @param hhash HASH handle.
754 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
755 * @param Size length of the input buffer in bytes.
756 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
757 * @param Timeout Timeout value
760 HAL_StatusTypeDef
HAL_HASH_MD5_Start(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Timeout
)
762 return HASH_Start(hhash
, pInBuffer
, Size
, pOutBuffer
, Timeout
, HASH_ALGOSELECTION_MD5
);
766 * @brief If not already done, initialize the HASH peripheral in MD5 mode then
767 * processes pInBuffer.
768 * @note Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed
769 * several input buffers back-to-back to the Peripheral that will yield a single
770 * HASH signature once all buffers have been entered. Wrap-up of input
771 * buffers feeding and retrieval of digest is done by a call to
772 * HAL_HASH_MD5_Accmlt_End().
773 * @note Field hhash->Phase of HASH handle is tested to check whether or not
774 * the Peripheral has already been initialized.
775 * @note Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End()
776 * to read it, feeding at the same time the last input buffer to the Peripheral.
777 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
778 * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able
779 * to manage the ending buffer with a length in bytes not a multiple of 4.
780 * @param hhash HASH handle.
781 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
782 * @param Size length of the input buffer in bytes, must be a multiple of 4.
785 HAL_StatusTypeDef
HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
)
787 return HASH_Accumulate(hhash
, pInBuffer
, Size
,HASH_ALGOSELECTION_MD5
);
791 * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API.
792 * @note Digest is available in pOutBuffer.
793 * @param hhash HASH handle.
794 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
795 * @param Size length of the input buffer in bytes.
796 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
797 * @param Timeout Timeout value
800 HAL_StatusTypeDef
HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Timeout
)
802 return HASH_Start(hhash
, pInBuffer
, Size
, pOutBuffer
, Timeout
, HASH_ALGOSELECTION_MD5
);
806 * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
807 * read the computed digest.
808 * @note Digest is available in pOutBuffer.
809 * @param hhash HASH handle.
810 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
811 * @param Size length of the input buffer in bytes.
812 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
813 * @param Timeout Timeout value
816 HAL_StatusTypeDef
HAL_HASH_SHA1_Start(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Timeout
)
818 return HASH_Start(hhash
, pInBuffer
, Size
, pOutBuffer
, Timeout
, HASH_ALGOSELECTION_SHA1
);
822 * @brief If not already done, initialize the HASH peripheral in SHA1 mode then
823 * processes pInBuffer.
824 * @note Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed
825 * several input buffers back-to-back to the Peripheral that will yield a single
826 * HASH signature once all buffers have been entered. Wrap-up of input
827 * buffers feeding and retrieval of digest is done by a call to
828 * HAL_HASH_SHA1_Accmlt_End().
829 * @note Field hhash->Phase of HASH handle is tested to check whether or not
830 * the Peripheral has already been initialized.
831 * @note Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End()
832 * to read it, feeding at the same time the last input buffer to the Peripheral.
833 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
834 * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able
835 * to manage the ending buffer with a length in bytes not a multiple of 4.
836 * @param hhash HASH handle.
837 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
838 * @param Size length of the input buffer in bytes, must be a multiple of 4.
841 HAL_StatusTypeDef
HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
)
843 return HASH_Accumulate(hhash
, pInBuffer
, Size
,HASH_ALGOSELECTION_SHA1
);
847 * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API.
848 * @note Digest is available in pOutBuffer.
849 * @param hhash HASH handle.
850 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
851 * @param Size length of the input buffer in bytes.
852 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
853 * @param Timeout Timeout value
856 HAL_StatusTypeDef
HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Timeout
)
858 return HASH_Start(hhash
, pInBuffer
, Size
, pOutBuffer
, Timeout
, HASH_ALGOSELECTION_SHA1
);
865 /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode
866 * @brief HASH processing functions using interrupt mode.
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:
875 (++) HAL_HASH_MD5_Start_IT()
876 (++) HAL_HASH_MD5_Accmlt_IT()
877 (++) HAL_HASH_MD5_Accmlt_End_IT()
879 (++) HAL_HASH_SHA1_Start_IT()
880 (++) HAL_HASH_SHA1_Accmlt_IT()
881 (++) HAL_HASH_SHA1_Accmlt_End_IT()
883 [..] API HAL_HASH_IRQHandler() manages each HASH interruption.
885 [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in
886 HMAC processing mode.
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.
903 HAL_StatusTypeDef
HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
)
905 return HASH_Start_IT(hhash
, pInBuffer
, Size
, pOutBuffer
,HASH_ALGOSELECTION_MD5
);
909 * @brief If not already done, initialize the HASH peripheral in MD5 mode then
910 * processes pInBuffer in interruption mode.
911 * @note Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed
912 * several input buffers back-to-back to the Peripheral that will yield a single
913 * HASH signature once all buffers have been entered. Wrap-up of input
914 * buffers feeding and retrieval of digest is done by a call to
915 * HAL_HASH_MD5_Accmlt_End_IT().
916 * @note Field hhash->Phase of HASH handle is tested to check whether or not
917 * the Peripheral has already been initialized.
918 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
919 * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able
920 * to manage the ending buffer with a length in bytes not a multiple of 4.
921 * @param hhash HASH handle.
922 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
923 * @param Size length of the input buffer in bytes, must be a multiple of 4.
926 HAL_StatusTypeDef
HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
)
928 return HASH_Accumulate_IT(hhash
, pInBuffer
, Size
,HASH_ALGOSELECTION_MD5
);
932 * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API.
933 * @note Digest is available in pOutBuffer.
934 * @param hhash HASH handle.
935 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
936 * @param Size length of the input buffer in bytes.
937 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
940 HAL_StatusTypeDef
HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
)
942 return HASH_Start_IT(hhash
, pInBuffer
, Size
, pOutBuffer
,HASH_ALGOSELECTION_MD5
);
946 * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
947 * read the computed digest in interruption mode.
948 * @note Digest is available in pOutBuffer.
949 * @param hhash HASH handle.
950 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
951 * @param Size length of the input buffer in bytes.
952 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
955 HAL_StatusTypeDef
HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
)
957 return HASH_Start_IT(hhash
, pInBuffer
, Size
, pOutBuffer
,HASH_ALGOSELECTION_SHA1
);
962 * @brief If not already done, initialize the HASH peripheral in SHA1 mode then
963 * processes pInBuffer in interruption mode.
964 * @note Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed
965 * several input buffers back-to-back to the Peripheral that will yield a single
966 * HASH signature once all buffers have been entered. Wrap-up of input
967 * buffers feeding and retrieval of digest is done by a call to
968 * HAL_HASH_SHA1_Accmlt_End_IT().
969 * @note Field hhash->Phase of HASH handle is tested to check whether or not
970 * the Peripheral has already been initialized.
971 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
972 * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able
973 * to manage the ending buffer with a length in bytes not a multiple of 4.
974 * @param hhash HASH handle.
975 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
976 * @param Size length of the input buffer in bytes, must be a multiple of 4.
979 HAL_StatusTypeDef
HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
)
981 return HASH_Accumulate_IT(hhash
, pInBuffer
, Size
,HASH_ALGOSELECTION_SHA1
);
985 * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API.
986 * @note Digest is available in pOutBuffer.
987 * @param hhash HASH handle.
988 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
989 * @param Size length of the input buffer in bytes.
990 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
993 HAL_StatusTypeDef
HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
)
995 return HASH_Start_IT(hhash
, pInBuffer
, Size
, pOutBuffer
,HASH_ALGOSELECTION_SHA1
);
999 * @brief Handle HASH interrupt request.
1000 * @param hhash HASH handle.
1001 * @note HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well.
1002 * @note In case of error reported during the HASH interruption processing,
1003 * HAL_HASH_ErrorCallback() API is called so that user code can
1004 * manage the error. The error type is available in hhash->Status field.
1007 void HAL_HASH_IRQHandler(HASH_HandleTypeDef
*hhash
)
1009 hhash
->Status
= HASH_IT(hhash
);
1010 if (hhash
->Status
!= HAL_OK
)
1012 hhash
->ErrorCode
|= HAL_HASH_ERROR_IT
;
1013 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1014 hhash
->ErrorCallback(hhash
);
1016 HAL_HASH_ErrorCallback(hhash
);
1017 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1018 /* After error handling by code user, reset HASH handle HAL status */
1019 hhash
->Status
= HAL_OK
;
1027 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode
1028 * @brief HASH processing functions using DMA mode.
1031 ===============================================================================
1032 ##### DMA mode HASH processing functions #####
1033 ===============================================================================
1034 [..] This section provides functions allowing to calculate in DMA mode
1035 the hash value using one of the following algorithms:
1037 (++) HAL_HASH_MD5_Start_DMA()
1038 (++) HAL_HASH_MD5_Finish()
1040 (++) HAL_HASH_SHA1_Start_DMA()
1041 (++) HAL_HASH_SHA1_Finish()
1043 [..] When resorting to DMA mode to enter the data in the Peripheral, user must resort
1044 to HAL_HASH_xxx_Start_DMA() then read the resulting digest with
1045 HAL_HASH_xxx_Finish().
1046 [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before
1047 the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be
1048 reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally
1049 retrieved thanks to HAL_HASH_xxx_Finish().
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
1065 HAL_StatusTypeDef
HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
)
1067 return HASH_Start_DMA(hhash
, pInBuffer
, Size
, HASH_ALGOSELECTION_MD5
);
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
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
1080 HAL_StatusTypeDef
HAL_HASH_MD5_Finish(HASH_HandleTypeDef
*hhash
, uint8_t* pOutBuffer
, uint32_t Timeout
)
1082 return HASH_Finish(hhash
, pOutBuffer
, Timeout
);
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
1095 HAL_StatusTypeDef
HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
)
1097 return HASH_Start_DMA(hhash
, pInBuffer
, Size
, HASH_ALGOSELECTION_SHA1
);
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
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
1111 HAL_StatusTypeDef
HAL_HASH_SHA1_Finish(HASH_HandleTypeDef
*hhash
, uint8_t* pOutBuffer
, uint32_t Timeout
)
1113 return HASH_Finish(hhash
, pOutBuffer
, Timeout
);
1120 /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode
1121 * @brief HMAC processing functions using polling mode.
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:
1130 (++) HAL_HMAC_MD5_Start()
1132 (++) HAL_HMAC_SHA1_Start()
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
1152 HAL_StatusTypeDef
HAL_HMAC_MD5_Start(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Timeout
)
1154 return HMAC_Start(hhash
, pInBuffer
, Size
, pOutBuffer
, Timeout
, HASH_ALGOSELECTION_MD5
);
1158 * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1159 * read the computed digest.
1160 * @note Digest is available in pOutBuffer.
1161 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1162 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1163 * @param hhash HASH handle.
1164 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
1165 * @param Size length of the input buffer in bytes.
1166 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1167 * @param Timeout Timeout value.
1168 * @retval HAL status
1170 HAL_StatusTypeDef
HAL_HMAC_SHA1_Start(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Timeout
)
1172 return HMAC_Start(hhash
, pInBuffer
, Size
, pOutBuffer
, Timeout
, HASH_ALGOSELECTION_SHA1
);
1180 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
1181 * @brief HMAC processing functions using interrupt mode.
1184 ===============================================================================
1185 ##### Interrupt mode HMAC processing functions #####
1186 ===============================================================================
1187 [..] This section provides functions allowing to calculate in interrupt mode
1188 the HMAC value using one of the following algorithms:
1190 (++) HAL_HMAC_MD5_Start_IT()
1192 (++) HAL_HMAC_SHA1_Start_IT()
1200 * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1201 * read the computed digest in interrupt mode.
1202 * @note Digest is available in pOutBuffer.
1203 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1204 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1205 * @param hhash HASH handle.
1206 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
1207 * @param Size length of the input buffer in bytes.
1208 * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1209 * @retval HAL status
1211 HAL_StatusTypeDef
HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
)
1213 return HMAC_Start_IT(hhash
, pInBuffer
, Size
, pOutBuffer
, HASH_ALGOSELECTION_MD5
);
1217 * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1218 * read the computed digest in interrupt mode.
1219 * @note Digest is available in pOutBuffer.
1220 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1221 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1222 * @param hhash HASH handle.
1223 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
1224 * @param Size length of the input buffer in bytes.
1225 * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1226 * @retval HAL status
1228 HAL_StatusTypeDef
HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
)
1230 return HMAC_Start_IT(hhash
, pInBuffer
, Size
, pOutBuffer
, HASH_ALGOSELECTION_SHA1
);
1239 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
1240 * @brief HMAC processing functions using DMA modes.
1243 ===============================================================================
1244 ##### DMA mode HMAC processing functions #####
1245 ===============================================================================
1246 [..] This section provides functions allowing to calculate in DMA mode
1247 the HMAC value using one of the following algorithms:
1249 (++) HAL_HMAC_MD5_Start_DMA()
1251 (++) HAL_HMAC_SHA1_Start_DMA()
1253 [..] When resorting to DMA mode to enter the data in the Peripheral for HMAC processing,
1254 user must resort to HAL_HMAC_xxx_Start_DMA() then read the resulting digest
1255 with HAL_HASH_xxx_Finish().
1263 * @brief Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
1264 * DMA transfers to feed the key and the input buffer to the Peripheral.
1265 * @note Once the DMA transfers are finished (indicated by hhash->State set back
1266 * to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
1267 * the computed digest.
1268 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1269 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1270 * @note If MDMAT bit is set before calling this function (multi-buffer
1271 * HASH processing case), the input buffer size (in bytes) must be
1272 * a multiple of 4 otherwise, the HASH digest computation is corrupted.
1273 * For the processing of the last buffer of the thread, MDMAT bit must
1274 * be reset and the buffer length (in bytes) doesn't have to be a
1276 * @param hhash HASH handle.
1277 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
1278 * @param Size length of the input buffer in bytes.
1279 * @retval HAL status
1281 HAL_StatusTypeDef
HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
)
1283 return HMAC_Start_DMA(hhash
, pInBuffer
, Size
, HASH_ALGOSELECTION_MD5
);
1288 * @brief Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
1289 * DMA transfers to feed the key and the input buffer to the Peripheral.
1290 * @note Once the DMA transfers are finished (indicated by hhash->State set back
1291 * to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
1292 * the computed digest.
1293 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1294 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1295 * @note If MDMAT bit is set before calling this function (multi-buffer
1296 * HASH processing case), the input buffer size (in bytes) must be
1297 * a multiple of 4 otherwise, the HASH digest computation is corrupted.
1298 * For the processing of the last buffer of the thread, MDMAT bit must
1299 * be reset and the buffer length (in bytes) doesn't have to be a
1301 * @param hhash HASH handle.
1302 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
1303 * @param Size length of the input buffer in bytes.
1304 * @retval HAL status
1306 HAL_StatusTypeDef
HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
)
1308 return HMAC_Start_DMA(hhash
, pInBuffer
, Size
, HASH_ALGOSELECTION_SHA1
);
1315 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
1316 * @brief Peripheral State functions.
1319 ===============================================================================
1320 ##### Peripheral State methods #####
1321 ===============================================================================
1323 This section permits to get in run-time the state and the peripheral handle
1324 status of the peripheral:
1325 (+) HAL_HASH_GetState()
1326 (+) HAL_HASH_GetStatus()
1329 Additionally, this subsection provides functions allowing to save and restore
1330 the HASH or HMAC processing context in case of calculation suspension:
1331 (+) HAL_HASH_ContextSaving()
1332 (+) HAL_HASH_ContextRestoring()
1335 This subsection provides functions allowing to suspend the HASH processing
1336 (+) when input are fed to the Peripheral by software
1337 (++) HAL_HASH_SwFeed_ProcessSuspend()
1338 (+) when input are fed to the Peripheral by DMA
1339 (++) HAL_HASH_DMAFeed_ProcessSuspend()
1348 * @brief Return the HASH handle state.
1349 * @note The API yields the current state of the handle (BUSY, READY,...).
1350 * @param hhash HASH handle.
1351 * @retval HAL HASH state
1353 HAL_HASH_StateTypeDef
HAL_HASH_GetState(HASH_HandleTypeDef
*hhash
)
1355 return hhash
->State
;
1360 * @brief Return the HASH HAL status.
1361 * @note The API yields the HAL status of the handle: it is the result of the
1362 * latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
1363 * @param hhash HASH handle.
1364 * @retval HAL status
1366 HAL_StatusTypeDef
HAL_HASH_GetStatus(HASH_HandleTypeDef
*hhash
)
1368 return hhash
->Status
;
1372 * @brief Save the HASH context in case of processing suspension.
1373 * @param hhash HASH handle.
1374 * @param pMemBuffer pointer to the memory buffer where the HASH context
1376 * @note The IMR, STR, CR then all the CSR registers are saved
1377 * in that order. Only the r/w bits are read to be restored later on.
1378 * @note By default, all the context swap registers (there are
1379 * HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
1380 * @note pMemBuffer points to a buffer allocated by the user. The buffer size
1381 * must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
1384 void HAL_HASH_ContextSaving(HASH_HandleTypeDef
*hhash
, uint8_t* pMemBuffer
)
1386 uint32_t mem_ptr
= (uint32_t)pMemBuffer
;
1387 uint32_t csr_ptr
= (uint32_t)HASH
->CSR
;
1390 /* Prevent unused argument(s) compilation warning */
1393 /* Save IMR register content */
1394 *(uint32_t*)(mem_ptr
) = READ_BIT(HASH
->IMR
,HASH_IT_DINI
|HASH_IT_DCI
);
1396 /* Save STR register content */
1397 *(uint32_t*)(mem_ptr
) = READ_BIT(HASH
->STR
,HASH_STR_NBLW
);
1399 /* Save CR register content */
1400 *(uint32_t*)(mem_ptr
) = READ_BIT(HASH
->CR
,HASH_CR_DMAE
|HASH_CR_DATATYPE
|HASH_CR_MODE
|HASH_CR_ALGO
|HASH_CR_LKEY
|HASH_CR_MDMAT
);
1402 /* By default, save all CSRs registers */
1403 for (i
= HASH_NUMBER_OF_CSR_REGISTERS
; i
>0U; i
--)
1405 *(uint32_t*)(mem_ptr
) = *(uint32_t*)(csr_ptr
);
1413 * @brief Restore the HASH context in case of processing resumption.
1414 * @param hhash HASH handle.
1415 * @param pMemBuffer pointer to the memory buffer where the HASH context
1417 * @note The IMR, STR, CR then all the CSR registers are restored
1418 * in that order. Only the r/w bits are restored.
1419 * @note By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
1420 * of those) are restored (all of them have been saved by default
1424 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef
*hhash
, uint8_t* pMemBuffer
)
1426 uint32_t mem_ptr
= (uint32_t)pMemBuffer
;
1427 uint32_t csr_ptr
= (uint32_t)HASH
->CSR
;
1430 /* Prevent unused argument(s) compilation warning */
1433 /* Restore IMR register content */
1434 WRITE_REG(HASH
->IMR
, (*(uint32_t*)(mem_ptr
)));
1436 /* Restore STR register content */
1437 WRITE_REG(HASH
->STR
, (*(uint32_t*)(mem_ptr
)));
1439 /* Restore CR register content */
1440 WRITE_REG(HASH
->CR
, (*(uint32_t*)(mem_ptr
)));
1443 /* Reset the HASH processor before restoring the Context
1444 Swap Registers (CSR) */
1447 /* By default, restore all CSR registers */
1448 for (i
= HASH_NUMBER_OF_CSR_REGISTERS
; i
>0U; i
--)
1450 WRITE_REG((*(uint32_t*)(csr_ptr
)), (*(uint32_t*)(mem_ptr
)));
1458 * @brief Initiate HASH processing suspension when in polling or interruption mode.
1459 * @param hhash HASH handle.
1460 * @note Set the handle field SuspendRequest to the appropriate value so that
1461 * the on-going HASH processing is suspended as soon as the required
1462 * conditions are met. Note that the actual suspension is carried out
1463 * by the functions HASH_WriteData() in polling mode and HASH_IT() in
1464 * interruption mode.
1467 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef
*hhash
)
1469 /* Set Handle Suspend Request field */
1470 hhash
->SuspendRequest
= HAL_HASH_SUSPEND
;
1474 * @brief Suspend the HASH processing when in DMA mode.
1475 * @param hhash HASH handle.
1476 * @note When suspension attempt occurs at the very end of a DMA transfer and
1477 * all the data have already been entered in the Peripheral, hhash->State is
1478 * set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
1479 * recommended to wrap-up the processing in reading the digest as usual.
1480 * @retval HAL status
1482 HAL_StatusTypeDef
HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef
*hhash
)
1484 uint32_t tmp_remaining_DMATransferSize_inWords
;
1485 uint32_t tmp_initial_DMATransferSize_inWords
;
1486 uint32_t tmp_words_already_pushed
;
1488 if (hhash
->State
== HAL_HASH_STATE_READY
)
1495 /* Make sure there is enough time to suspend the processing */
1496 tmp_remaining_DMATransferSize_inWords
= ((DMA_Stream_TypeDef
*)hhash
->hdmain
->Instance
)->NDTR
;
1498 if (tmp_remaining_DMATransferSize_inWords
<= HASH_DMA_SUSPENSION_WORDS_LIMIT
)
1500 /* No suspension attempted since almost to the end of the transferred data. */
1501 /* Best option for user code is to wrap up low priority message hashing */
1505 /* Wait for BUSY flag to be reset */
1506 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_BUSY
, SET
, HASH_TIMEOUTVALUE
) != HAL_OK
)
1511 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS
) != RESET
)
1516 /* Wait for BUSY flag to be set */
1517 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_BUSY
, RESET
, HASH_TIMEOUTVALUE
) != HAL_OK
)
1521 /* Disable DMA channel */
1522 /* Note that the Abort function will
1523 - Clear the transfer error flags
1527 if (HAL_DMA_Abort(hhash
->hdmain
) !=HAL_OK
)
1532 /* Clear DMAE bit */
1533 CLEAR_BIT(HASH
->CR
,HASH_CR_DMAE
);
1535 /* Wait for BUSY flag to be reset */
1536 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_BUSY
, SET
, HASH_TIMEOUTVALUE
) != HAL_OK
)
1541 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS
) != RESET
)
1546 /* At this point, DMA interface is disabled and no transfer is on-going */
1547 /* Retrieve from the DMA handle how many words remain to be written */
1548 tmp_remaining_DMATransferSize_inWords
= ((DMA_Stream_TypeDef
*)hhash
->hdmain
->Instance
)->NDTR
;
1550 if (tmp_remaining_DMATransferSize_inWords
== 0U)
1552 /* All the DMA transfer is actually done. Suspension occurred at the very end
1553 of the transfer. Either the digest computation is about to start (HASH case)
1554 or processing is about to move from one step to another (HMAC case).
1555 In both cases, the processing can't be suspended at this point. It is
1557 - retrieve the low priority block digest before starting the high
1558 priority block processing (HASH case)
1559 - re-attempt a new suspension (HMAC case)
1566 /* Compute how many words were supposed to be transferred by DMA */
1567 tmp_initial_DMATransferSize_inWords
= (((hhash
->HashInCount
%4U)!=0U) ? ((hhash
->HashInCount
+3U)/4U): (hhash
->HashInCount
/4U));
1569 /* If discrepancy between the number of words reported by DMA Peripheral and the numbers of words entered as reported
1570 by HASH Peripheral, correct it */
1571 /* tmp_words_already_pushed reflects the number of words that were already pushed before
1572 the start of DMA transfer (multi-buffer processing case) */
1573 tmp_words_already_pushed
= hhash
->NbWordsAlreadyPushed
;
1574 if (((tmp_words_already_pushed
+ tmp_initial_DMATransferSize_inWords
- tmp_remaining_DMATransferSize_inWords
) %16U) != HASH_NBW_PUSHED())
1576 tmp_remaining_DMATransferSize_inWords
--; /* one less word to be transferred again */
1579 /* Accordingly, update the input pointer that points at the next word to be transferred to the Peripheral by DMA */
1580 hhash
->pHashInBuffPtr
+= 4U * (tmp_initial_DMATransferSize_inWords
- tmp_remaining_DMATransferSize_inWords
) ;
1582 /* And store in HashInCount the remaining size to transfer (in bytes) */
1583 hhash
->HashInCount
= 4U * tmp_remaining_DMATransferSize_inWords
;
1587 /* Set State as suspended */
1588 hhash
->State
= HAL_HASH_STATE_SUSPENDED
;
1596 * @brief Return the HASH handle error code.
1597 * @param hhash pointer to a HASH_HandleTypeDef structure.
1598 * @retval HASH Error Code
1600 uint32_t HAL_HASH_GetError(HASH_HandleTypeDef
*hhash
)
1602 /* Return HASH Error Code */
1603 return hhash
->ErrorCode
;
1614 /** @defgroup HASH_Private_Functions HASH Private Functions
1619 * @brief DMA HASH Input Data transfer completion callback.
1620 * @param hdma DMA handle.
1621 * @note In case of HMAC processing, HASH_DMAXferCplt() initiates
1622 * the next DMA transfer for the following HMAC step.
1625 static void HASH_DMAXferCplt(DMA_HandleTypeDef
*hdma
)
1627 HASH_HandleTypeDef
* hhash
= ( HASH_HandleTypeDef
* )((DMA_HandleTypeDef
* )hdma
)->Parent
;
1629 uint32_t buffersize
;
1630 HAL_StatusTypeDef status
;
1632 if (hhash
->State
!= HAL_HASH_STATE_SUSPENDED
)
1635 /* Disable the DMA transfer */
1636 CLEAR_BIT(HASH
->CR
, HASH_CR_DMAE
);
1638 if (READ_BIT(HASH
->CR
, HASH_CR_MODE
) == 0U)
1640 /* If no HMAC processing, input data transfer is now over */
1642 /* Change the HASH state to ready */
1643 hhash
->State
= HAL_HASH_STATE_READY
;
1645 /* Call Input data transfer complete call back */
1646 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1647 hhash
->InCpltCallback(hhash
);
1649 HAL_HASH_InCpltCallback(hhash
);
1650 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1655 /* HMAC processing: depending on the current HMAC step and whether or
1656 not multi-buffer processing is on-going, the next step is initiated
1657 and MDMAT bit is set. */
1660 if (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_3
)
1662 /* This is the end of HMAC processing */
1664 /* Change the HASH state to ready */
1665 hhash
->State
= HAL_HASH_STATE_READY
;
1667 /* Call Input data transfer complete call back
1668 (note that the last DMA transfer was that of the key
1669 for the outer HASH operation). */
1670 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1671 hhash
->InCpltCallback(hhash
);
1673 HAL_HASH_InCpltCallback(hhash
);
1674 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1678 else if (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_1
)
1680 inputaddr
= (uint32_t)hhash
->pHashMsgBuffPtr
; /* DMA transfer start address */
1681 buffersize
= hhash
->HashBuffSize
; /* DMA transfer size (in bytes) */
1682 hhash
->Phase
= HAL_HASH_PHASE_HMAC_STEP_2
; /* Move phase from Step 1 to Step 2 */
1684 /* In case of suspension request, save the new starting parameters */
1685 hhash
->HashInCount
= hhash
->HashBuffSize
; /* Initial DMA transfer size (in bytes) */
1686 hhash
->pHashInBuffPtr
= hhash
->pHashMsgBuffPtr
; /* DMA transfer start address */
1688 hhash
->NbWordsAlreadyPushed
= 0U; /* Reset number of words already pushed */
1689 /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */
1690 if (hhash
->DigestCalculationDisable
!= RESET
)
1692 /* Digest calculation is disabled: Step 2 must start with MDMAT bit set,
1693 no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */
1694 __HAL_HASH_SET_MDMAT();
1697 else /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
1699 if (hhash
->DigestCalculationDisable
!= RESET
)
1701 /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral
1702 (case of multi-buffer HMAC processing):
1703 DCAL must not be set.
1704 Phase remains in Step 2, MDMAT remains set at this point.
1705 Change the HASH state to ready and call Input data transfer complete call back. */
1706 hhash
->State
= HAL_HASH_STATE_READY
;
1707 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1708 hhash
->InCpltCallback(hhash
);
1710 HAL_HASH_InCpltCallback(hhash
);
1711 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1716 /* Digest calculation is not disabled (case of single buffer input or last buffer
1717 of multi-buffer HMAC processing) */
1718 inputaddr
= (uint32_t)hhash
->Init
.pKey
; /* DMA transfer start address */
1719 buffersize
= hhash
->Init
.KeySize
; /* DMA transfer size (in bytes) */
1720 hhash
->Phase
= HAL_HASH_PHASE_HMAC_STEP_3
; /* Move phase from Step 2 to Step 3 */
1721 /* In case of suspension request, save the new starting parameters */
1722 hhash
->HashInCount
= hhash
->Init
.KeySize
; /* Initial size for second DMA transfer (input data) */
1723 hhash
->pHashInBuffPtr
= hhash
->Init
.pKey
; /* address passed to DMA, now entering data message */
1725 hhash
->NbWordsAlreadyPushed
= 0U; /* Reset number of words already pushed */
1729 /* Configure the Number of valid bits in last word of the message */
1730 __HAL_HASH_SET_NBVALIDBITS(buffersize
);
1732 /* Set the HASH DMA transfert completion call back */
1733 hhash
->hdmain
->XferCpltCallback
= HASH_DMAXferCplt
;
1735 /* Enable the DMA In DMA Stream */
1736 status
= HAL_DMA_Start_IT(hhash
->hdmain
, inputaddr
, (uint32_t)&HASH
->DIN
, (((buffersize
%4U)!=0U) ? ((buffersize
+(4U-(buffersize
%4U)))/4U):(buffersize
/4U)));
1738 /* Enable DMA requests */
1739 SET_BIT(HASH
->CR
, HASH_CR_DMAE
);
1741 /* Return function status */
1742 if (status
!= HAL_OK
)
1744 /* Update HASH state machine to error */
1745 hhash
->State
= HAL_HASH_STATE_ERROR
;
1749 /* Change HASH state */
1750 hhash
->State
= HAL_HASH_STATE_READY
;
1759 * @brief DMA HASH communication error callback.
1760 * @param hdma DMA handle.
1761 * @note HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
1762 * can contain user code to manage the error.
1765 static void HASH_DMAError(DMA_HandleTypeDef
*hdma
)
1767 HASH_HandleTypeDef
* hhash
= ( HASH_HandleTypeDef
* )((DMA_HandleTypeDef
* )hdma
)->Parent
;
1769 if (hhash
->State
!= HAL_HASH_STATE_SUSPENDED
)
1771 hhash
->ErrorCode
|= HAL_HASH_ERROR_DMA
;
1772 /* Set HASH state to ready to prevent any blocking issue in user code
1773 present in HAL_HASH_ErrorCallback() */
1774 hhash
->State
= HAL_HASH_STATE_READY
;
1775 /* Set HASH handle status to error */
1776 hhash
->Status
= HAL_ERROR
;
1777 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1778 hhash
->ErrorCallback(hhash
);
1780 HAL_HASH_ErrorCallback(hhash
);
1781 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1782 /* After error handling by code user, reset HASH handle HAL status */
1783 hhash
->Status
= HAL_OK
;
1789 * @brief Feed the input buffer to the HASH Peripheral.
1790 * @param hhash HASH handle.
1791 * @param pInBuffer pointer to input buffer.
1792 * @param Size the size of input buffer in bytes.
1793 * @note HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
1794 * or not the HASH processing must be suspended. If this is the case, the
1795 * processing is suspended when possible and the Peripheral feeding point reached at
1796 * suspension time is stored in the handle for resumption later on.
1797 * @retval HAL status
1799 static HAL_StatusTypeDef
HASH_WriteData(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
)
1801 uint32_t buffercounter
;
1802 __IO
uint32_t inputaddr
= (uint32_t) pInBuffer
;
1804 for(buffercounter
= 0U; buffercounter
< Size
; buffercounter
+=4U)
1806 /* Write input data 4 bytes at a time */
1807 HASH
->DIN
= *(uint32_t*)inputaddr
;
1810 /* If the suspension flag has been raised and if the processing is not about
1811 to end, suspend processing */
1812 if ((hhash
->SuspendRequest
== HAL_HASH_SUSPEND
) && ((buffercounter
+4U) < Size
))
1814 /* wait for flag BUSY not set before Wait for DINIS = 1*/
1815 if (buffercounter
>=64U)
1817 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_BUSY
, SET
, HASH_TIMEOUTVALUE
) != HAL_OK
)
1822 /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
1823 in the input buffer */
1824 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS
))
1826 /* Reset SuspendRequest */
1827 hhash
->SuspendRequest
= HAL_HASH_SUSPEND_NONE
;
1829 /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
1830 reached at suspension time is not saved in the same handle fields */
1831 if ((hhash
->Phase
== HAL_HASH_PHASE_PROCESS
) || (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_2
))
1833 /* Save current reading and writing locations of Input and Output buffers */
1834 hhash
->pHashInBuffPtr
= (uint8_t *)inputaddr
;
1835 /* Save the number of bytes that remain to be processed at this point */
1836 hhash
->HashInCount
= Size
- (buffercounter
+ 4U);
1838 else if ((hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_1
) || (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_3
))
1840 /* Save current reading and writing locations of Input and Output buffers */
1841 hhash
->pHashKeyBuffPtr
= (uint8_t *)inputaddr
;
1842 /* Save the number of bytes that remain to be processed at this point */
1843 hhash
->HashKeyCount
= Size
- (buffercounter
+ 4U);
1847 /* Unexpected phase: unlock process and report error */
1848 hhash
->State
= HAL_HASH_STATE_READY
;
1849 __HAL_UNLOCK(hhash
);
1853 /* Set the HASH state to Suspended and exit to stop entering data */
1854 hhash
->State
= HAL_HASH_STATE_SUSPENDED
;
1857 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) */
1858 } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
1859 } /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4) */
1861 /* At this point, all the data have been entered to the Peripheral: exit */
1866 * @brief Retrieve the message digest.
1867 * @param pMsgDigest pointer to the computed digest.
1868 * @param Size message digest size in bytes.
1871 static void HASH_GetDigest(uint8_t *pMsgDigest
, uint8_t Size
)
1873 uint32_t msgdigest
= (uint32_t)pMsgDigest
;
1877 /* Read the message digest */
1879 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[0]);
1881 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[1]);
1883 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[2]);
1885 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[3]);
1888 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[0]);
1890 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[1]);
1892 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[2]);
1894 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[3]);
1896 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[4]);
1898 case 28: /* SHA224 */
1899 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[0]);
1901 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[1]);
1903 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[2]);
1905 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[3]);
1907 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[4]);
1909 *(uint32_t*)(msgdigest
) = __REV(HASH_DIGEST
->HR
[5]);
1911 *(uint32_t*)(msgdigest
) = __REV(HASH_DIGEST
->HR
[6]);
1913 case 32: /* SHA256 */
1914 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[0]);
1916 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[1]);
1918 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[2]);
1920 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[3]);
1922 *(uint32_t*)(msgdigest
) = __REV(HASH
->HR
[4]);
1924 *(uint32_t*)(msgdigest
) = __REV(HASH_DIGEST
->HR
[5]);
1926 *(uint32_t*)(msgdigest
) = __REV(HASH_DIGEST
->HR
[6]);
1928 *(uint32_t*)(msgdigest
) = __REV(HASH_DIGEST
->HR
[7]);
1938 * @brief Handle HASH processing Timeout.
1939 * @param hhash HASH handle.
1940 * @param Flag specifies the HASH flag to check.
1941 * @param Status the Flag status (SET or RESET).
1942 * @param Timeout Timeout duration.
1943 * @retval HAL status
1945 static HAL_StatusTypeDef
HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef
*hhash
, uint32_t Flag
, FlagStatus Status
, uint32_t Timeout
)
1947 uint32_t tickstart
= HAL_GetTick();
1949 /* Wait until flag is set */
1952 while(__HAL_HASH_GET_FLAG(Flag
) == RESET
)
1954 /* Check for the Timeout */
1955 if(Timeout
!= HAL_MAX_DELAY
)
1957 if(((HAL_GetTick()-tickstart
) > Timeout
) || (Timeout
== 0U))
1959 /* Set State to Ready to be able to restart later on */
1960 hhash
->State
= HAL_HASH_STATE_READY
;
1961 /* Store time out issue in handle status */
1962 hhash
->Status
= HAL_TIMEOUT
;
1964 /* Process Unlocked */
1965 __HAL_UNLOCK(hhash
);
1974 while(__HAL_HASH_GET_FLAG(Flag
) != RESET
)
1976 /* Check for the Timeout */
1977 if(Timeout
!= HAL_MAX_DELAY
)
1979 if(((HAL_GetTick()-tickstart
) > Timeout
) || (Timeout
== 0U))
1981 /* Set State to Ready to be able to restart later on */
1982 hhash
->State
= HAL_HASH_STATE_READY
;
1983 /* Store time out issue in handle status */
1984 hhash
->Status
= HAL_TIMEOUT
;
1986 /* Process Unlocked */
1987 __HAL_UNLOCK(hhash
);
1999 * @brief HASH processing in interruption mode.
2000 * @param hhash HASH handle.
2001 * @note HASH_IT() regularly reads hhash->SuspendRequest to check whether
2002 * or not the HASH processing must be suspended. If this is the case, the
2003 * processing is suspended when possible and the Peripheral feeding point reached at
2004 * suspension time is stored in the handle for resumption later on.
2005 * @retval HAL status
2007 static HAL_StatusTypeDef
HASH_IT(HASH_HandleTypeDef
*hhash
)
2009 if (hhash
->State
== HAL_HASH_STATE_BUSY
)
2011 /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
2012 if(hhash
->HashITCounter
== 0U)
2014 /* Disable Interrupts */
2015 __HAL_HASH_DISABLE_IT(HASH_IT_DINI
|HASH_IT_DCI
);
2016 /* HASH state set back to Ready to prevent any issue in user code
2017 present in HAL_HASH_ErrorCallback() */
2018 hhash
->State
= HAL_HASH_STATE_READY
;
2021 else if (hhash
->HashITCounter
== 1U)
2023 /* This is the first call to HASH_IT, the first input data are about to be
2024 entered in the Peripheral. A specific processing is carried out at this point to
2025 start-up the processing. */
2026 hhash
->HashITCounter
= 2U;
2030 /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
2031 the HASH processing or the end of the current step for HMAC processing. */
2032 hhash
->HashITCounter
= 3U;
2035 /* If digest is ready */
2036 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS
))
2038 /* Read the digest */
2039 HASH_GetDigest(hhash
->pHashOutBuffPtr
, HASH_DIGEST_LENGTH());
2041 /* Disable Interrupts */
2042 __HAL_HASH_DISABLE_IT(HASH_IT_DINI
|HASH_IT_DCI
);
2043 /* Change the HASH state */
2044 hhash
->State
= HAL_HASH_STATE_READY
;
2045 /* Reset HASH state machine */
2046 hhash
->Phase
= HAL_HASH_PHASE_READY
;
2047 /* Call digest computation complete call back */
2048 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2049 hhash
->DgstCpltCallback(hhash
);
2051 HAL_HASH_DgstCpltCallback(hhash
);
2052 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2057 /* If Peripheral ready to accept new data */
2058 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS
))
2061 /* If the suspension flag has been raised and if the processing is not about
2062 to end, suspend processing */
2063 if ( (hhash
->HashInCount
!= 0U) && (hhash
->SuspendRequest
== HAL_HASH_SUSPEND
))
2065 /* Disable Interrupts */
2066 __HAL_HASH_DISABLE_IT(HASH_IT_DINI
|HASH_IT_DCI
);
2068 /* Reset SuspendRequest */
2069 hhash
->SuspendRequest
= HAL_HASH_SUSPEND_NONE
;
2071 /* Change the HASH state */
2072 hhash
->State
= HAL_HASH_STATE_SUSPENDED
;
2077 /* Enter input data in the Peripheral thru HASH_Write_Block_Data() call and
2078 check whether the digest calculation has been triggered */
2079 if (HASH_Write_Block_Data(hhash
) == HASH_DIGEST_CALCULATION_STARTED
)
2081 /* Call Input data transfer complete call back
2082 (called at the end of each step for HMAC) */
2083 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2084 hhash
->InCpltCallback(hhash
);
2086 HAL_HASH_InCpltCallback(hhash
);
2087 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2089 if (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_1
)
2091 /* Wait until Peripheral is not busy anymore */
2092 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_BUSY
, SET
, HASH_TIMEOUTVALUE
) != HAL_OK
)
2094 /* Disable Interrupts */
2095 __HAL_HASH_DISABLE_IT(HASH_IT_DINI
|HASH_IT_DCI
);
2098 /* Initialization start for HMAC STEP 2 */
2099 hhash
->Phase
= HAL_HASH_PHASE_HMAC_STEP_2
; /* Move phase from Step 1 to Step 2 */
2100 __HAL_HASH_SET_NBVALIDBITS(hhash
->HashBuffSize
); /* Set NBLW for the input message */
2101 hhash
->HashInCount
= hhash
->HashBuffSize
; /* Set the input data size (in bytes) */
2102 hhash
->pHashInBuffPtr
= hhash
->pHashMsgBuffPtr
; /* Set the input data address */
2103 hhash
->HashITCounter
= 1; /* Set ITCounter to 1 to indicate the start of a new phase */
2104 __HAL_HASH_ENABLE_IT(HASH_IT_DINI
); /* Enable IT (was disabled in HASH_Write_Block_Data) */
2106 else if (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_2
)
2108 /* Wait until Peripheral is not busy anymore */
2109 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_BUSY
, SET
, HASH_TIMEOUTVALUE
) != HAL_OK
)
2111 /* Disable Interrupts */
2112 __HAL_HASH_DISABLE_IT(HASH_IT_DINI
|HASH_IT_DCI
);
2115 /* Initialization start for HMAC STEP 3 */
2116 hhash
->Phase
= HAL_HASH_PHASE_HMAC_STEP_3
; /* Move phase from Step 2 to Step 3 */
2117 __HAL_HASH_SET_NBVALIDBITS(hhash
->Init
.KeySize
); /* Set NBLW for the key */
2118 hhash
->HashInCount
= hhash
->Init
.KeySize
; /* Set the key size (in bytes) */
2119 hhash
->pHashInBuffPtr
= hhash
->Init
.pKey
; /* Set the key address */
2120 hhash
->HashITCounter
= 1; /* Set ITCounter to 1 to indicate the start of a new phase */
2121 __HAL_HASH_ENABLE_IT(HASH_IT_DINI
); /* Enable IT (was disabled in HASH_Write_Block_Data) */
2127 } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
2128 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
2130 /* Return function status */
2141 * @brief Write a block of data in HASH Peripheral in interruption mode.
2142 * @param hhash HASH handle.
2143 * @note HASH_Write_Block_Data() is called under interruption by HASH_IT().
2144 * @retval HAL status
2146 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef
*hhash
)
2149 uint32_t buffercounter
;
2150 uint32_t inputcounter
;
2151 uint32_t ret
= HASH_DIGEST_CALCULATION_NOT_STARTED
;
2153 /* If there are more than 64 bytes remaining to be entered */
2154 if(hhash
->HashInCount
> 64U)
2156 inputaddr
= (uint32_t)hhash
->pHashInBuffPtr
;
2157 /* Write the Input block in the Data IN register
2158 (16 32-bit words, or 64 bytes are entered) */
2159 for(buffercounter
= 0U; buffercounter
< 64U; buffercounter
+=4U)
2161 HASH
->DIN
= *(uint32_t*)inputaddr
;
2164 /* If this is the start of input data entering, an additional word
2165 must be entered to start up the HASH processing */
2166 if(hhash
->HashITCounter
== 2U)
2168 HASH
->DIN
= *(uint32_t*)inputaddr
;
2169 if(hhash
->HashInCount
>= 68U)
2171 /* There are still data waiting to be entered in the Peripheral.
2172 Decrement buffer counter and set pointer to the proper
2173 memory location for the next data entering round. */
2174 hhash
->HashInCount
-= 68U;
2175 hhash
->pHashInBuffPtr
+= 68U;
2179 /* All the input buffer has been fed to the HW. */
2180 hhash
->HashInCount
= 0U;
2185 /* 64 bytes have been entered and there are still some remaining:
2186 Decrement buffer counter and set pointer to the proper
2187 memory location for the next data entering round.*/
2188 hhash
->HashInCount
-= 64U;
2189 hhash
->pHashInBuffPtr
+= 64U;
2194 /* 64 or less bytes remain to be entered. This is the last
2195 data entering round. */
2197 /* Get the buffer address */
2198 inputaddr
= (uint32_t)hhash
->pHashInBuffPtr
;
2199 /* Get the buffer counter */
2200 inputcounter
= hhash
->HashInCount
;
2201 /* Disable Interrupts */
2202 __HAL_HASH_DISABLE_IT(HASH_IT_DINI
);
2204 /* Write the Input block in the Data IN register */
2205 for(buffercounter
= 0U; buffercounter
< ((inputcounter
+3U)/4U); buffercounter
++)
2207 HASH
->DIN
= *(uint32_t*)inputaddr
;
2211 if (hhash
->Accumulation
== 1U)
2213 /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
2214 The digest computation will be started when the last buffer data are entered. */
2216 /* Reset multi buffers accumulation flag */
2217 hhash
->Accumulation
= 0U;
2218 /* Change the HASH state */
2219 hhash
->State
= HAL_HASH_STATE_READY
;
2220 /* Call Input data transfer complete call back */
2221 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2222 hhash
->InCpltCallback(hhash
);
2224 HAL_HASH_InCpltCallback(hhash
);
2225 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2229 /* Start the Digest calculation */
2230 __HAL_HASH_START_DIGEST();
2231 /* Return indication that digest calculation has started:
2232 this return value triggers the call to Input data transfer
2233 complete call back as well as the proper transition from
2234 one step to another in HMAC mode. */
2235 ret
= HASH_DIGEST_CALCULATION_STARTED
;
2237 /* Reset buffer counter */
2238 hhash
->HashInCount
= 0;
2241 /* Return whether or digest calculation has started */
2246 * @brief HMAC processing in polling mode.
2247 * @param hhash HASH handle.
2248 * @param Timeout Timeout value.
2249 * @retval HAL status
2251 static HAL_StatusTypeDef
HMAC_Processing(HASH_HandleTypeDef
*hhash
, uint32_t Timeout
)
2253 /* Ensure first that Phase is correct */
2254 if ((hhash
->Phase
!= HAL_HASH_PHASE_HMAC_STEP_1
) && (hhash
->Phase
!= HAL_HASH_PHASE_HMAC_STEP_2
) && (hhash
->Phase
!= HAL_HASH_PHASE_HMAC_STEP_3
))
2256 /* Change the HASH state */
2257 hhash
->State
= HAL_HASH_STATE_READY
;
2259 /* Process Unlock */
2260 __HAL_UNLOCK(hhash
);
2262 /* Return function status */
2266 /* HMAC Step 1 processing */
2267 if (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_1
)
2269 /************************** STEP 1 ******************************************/
2270 /* Configure the Number of valid bits in last word of the message */
2271 __HAL_HASH_SET_NBVALIDBITS(hhash
->Init
.KeySize
);
2273 /* Write input buffer in Data register */
2274 hhash
->Status
= HASH_WriteData(hhash
, hhash
->pHashKeyBuffPtr
, hhash
->HashKeyCount
);
2275 if (hhash
->Status
!= HAL_OK
)
2277 return hhash
->Status
;
2280 /* Check whether or not key entering process has been suspended */
2281 if (hhash
->State
== HAL_HASH_STATE_SUSPENDED
)
2283 /* Process Unlocked */
2284 __HAL_UNLOCK(hhash
);
2286 /* Stop right there and return function status */
2290 /* No processing suspension at this point: set DCAL bit. */
2291 __HAL_HASH_START_DIGEST();
2293 /* Wait for BUSY flag to be cleared */
2294 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_BUSY
, SET
, Timeout
) != HAL_OK
)
2299 /* Move from Step 1 to Step 2 */
2300 hhash
->Phase
= HAL_HASH_PHASE_HMAC_STEP_2
;
2304 /* HMAC Step 2 processing.
2305 After phase check, HMAC_Processing() may
2306 - directly start up from this point in resumption case
2307 if the same Step 2 processing was suspended previously
2308 - or fall through from the Step 1 processing carried out hereabove */
2309 if (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_2
)
2311 /************************** STEP 2 ******************************************/
2312 /* Configure the Number of valid bits in last word of the message */
2313 __HAL_HASH_SET_NBVALIDBITS(hhash
->HashBuffSize
);
2315 /* Write input buffer in Data register */
2316 hhash
->Status
= HASH_WriteData(hhash
, hhash
->pHashInBuffPtr
, hhash
->HashInCount
);
2317 if (hhash
->Status
!= HAL_OK
)
2319 return hhash
->Status
;
2322 /* Check whether or not data entering process has been suspended */
2323 if (hhash
->State
== HAL_HASH_STATE_SUSPENDED
)
2325 /* Process Unlocked */
2326 __HAL_UNLOCK(hhash
);
2328 /* Stop right there and return function status */
2332 /* No processing suspension at this point: set DCAL bit. */
2333 __HAL_HASH_START_DIGEST();
2335 /* Wait for BUSY flag to be cleared */
2336 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_BUSY
, SET
, Timeout
) != HAL_OK
)
2341 /* Move from Step 2 to Step 3 */
2342 hhash
->Phase
= HAL_HASH_PHASE_HMAC_STEP_3
;
2343 /* In case Step 1 phase was suspended then resumed,
2344 set again Key input buffers and size before moving to
2346 hhash
->pHashKeyBuffPtr
= hhash
->Init
.pKey
;
2347 hhash
->HashKeyCount
= hhash
->Init
.KeySize
;
2351 /* HMAC Step 3 processing.
2352 After phase check, HMAC_Processing() may
2353 - directly start up from this point in resumption case
2354 if the same Step 3 processing was suspended previously
2355 - or fall through from the Step 2 processing carried out hereabove */
2356 if (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_3
)
2358 /************************** STEP 3 ******************************************/
2359 /* Configure the Number of valid bits in last word of the message */
2360 __HAL_HASH_SET_NBVALIDBITS(hhash
->Init
.KeySize
);
2362 /* Write input buffer in Data register */
2363 hhash
->Status
= HASH_WriteData(hhash
, hhash
->pHashKeyBuffPtr
, hhash
->HashKeyCount
);
2364 if (hhash
->Status
!= HAL_OK
)
2366 return hhash
->Status
;
2369 /* Check whether or not key entering process has been suspended */
2370 if (hhash
->State
== HAL_HASH_STATE_SUSPENDED
)
2372 /* Process Unlocked */
2373 __HAL_UNLOCK(hhash
);
2375 /* Stop right there and return function status */
2379 /* No processing suspension at this point: start the Digest calculation. */
2380 __HAL_HASH_START_DIGEST();
2382 /* Wait for DCIS flag to be set */
2383 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_DCIS
, RESET
, Timeout
) != HAL_OK
)
2388 /* Read the message digest */
2389 HASH_GetDigest(hhash
->pHashOutBuffPtr
, HASH_DIGEST_LENGTH());
2391 /* Reset HASH state machine */
2392 hhash
->Phase
= HAL_HASH_PHASE_READY
;
2395 /* Change the HASH state */
2396 hhash
->State
= HAL_HASH_STATE_READY
;
2398 /* Process Unlock */
2399 __HAL_UNLOCK(hhash
);
2401 /* Return function status */
2407 * @brief Initialize the HASH peripheral, next process pInBuffer then
2408 * read the computed digest.
2409 * @note Digest is available in pOutBuffer.
2410 * @param hhash HASH handle.
2411 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
2412 * @param Size length of the input buffer in bytes.
2413 * @param pOutBuffer pointer to the computed digest.
2414 * @param Timeout Timeout value.
2415 * @param Algorithm HASH algorithm.
2416 * @retval HAL status
2418 HAL_StatusTypeDef
HASH_Start(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Timeout
, uint32_t Algorithm
)
2420 uint8_t *pInBuffer_tmp
; /* input data address, input parameter of HASH_WriteData() */
2421 uint32_t Size_tmp
; /* input data size (in bytes), input parameter of HASH_WriteData() */
2422 HAL_HASH_StateTypeDef State_tmp
= hhash
->State
;
2425 /* Initiate HASH processing in case of start or resumption */
2426 if((State_tmp
== HAL_HASH_STATE_READY
) || (State_tmp
== HAL_HASH_STATE_SUSPENDED
))
2428 /* Check input parameters */
2429 if ((pInBuffer
== NULL
) || (pOutBuffer
== NULL
))
2431 hhash
->State
= HAL_HASH_STATE_READY
;
2435 /* Process Locked */
2438 /* Check if initialization phase has not been already performed */
2439 if(hhash
->Phase
== HAL_HASH_PHASE_READY
)
2441 /* Change the HASH state */
2442 hhash
->State
= HAL_HASH_STATE_BUSY
;
2444 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2445 MODIFY_REG(HASH
->CR
, HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_CR_INIT
);
2447 /* Configure the number of valid bits in last word of the message */
2448 __HAL_HASH_SET_NBVALIDBITS(Size
);
2450 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2451 input parameters of HASH_WriteData() */
2452 pInBuffer_tmp
= pInBuffer
; /* pInBuffer_tmp is set to the input data address */
2453 Size_tmp
= Size
; /* Size_tmp contains the input data size in bytes */
2456 hhash
->Phase
= HAL_HASH_PHASE_PROCESS
;
2458 else if (hhash
->Phase
== HAL_HASH_PHASE_PROCESS
)
2460 /* if the Peripheral has already been initialized, two cases are possible */
2462 /* Process resumption time ... */
2463 if (hhash
->State
== HAL_HASH_STATE_SUSPENDED
)
2465 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2466 to the API input parameters but to those saved beforehand by HASH_WriteData()
2467 when the processing was suspended */
2468 pInBuffer_tmp
= hhash
->pHashInBuffPtr
;
2469 Size_tmp
= hhash
->HashInCount
;
2471 /* ... or multi-buffer HASH processing end */
2474 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2475 input parameters of HASH_WriteData() */
2476 pInBuffer_tmp
= pInBuffer
;
2478 /* Configure the number of valid bits in last word of the message */
2479 __HAL_HASH_SET_NBVALIDBITS(Size
);
2481 /* Change the HASH state */
2482 hhash
->State
= HAL_HASH_STATE_BUSY
;
2487 hhash
->State
= HAL_HASH_STATE_READY
;
2489 /* Process Unlocked */
2490 __HAL_UNLOCK(hhash
);
2492 /* Return function status */
2497 /* Write input buffer in Data register */
2498 hhash
->Status
= HASH_WriteData(hhash
, pInBuffer_tmp
, Size_tmp
);
2499 if (hhash
->Status
!= HAL_OK
)
2501 return hhash
->Status
;
2504 /* If the process has not been suspended, carry on to digest calculation */
2505 if (hhash
->State
!= HAL_HASH_STATE_SUSPENDED
)
2507 /* Start the Digest calculation */
2508 __HAL_HASH_START_DIGEST();
2510 /* Wait for DCIS flag to be set */
2511 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_DCIS
, RESET
, Timeout
) != HAL_OK
)
2516 /* Read the message digest */
2517 HASH_GetDigest(pOutBuffer
, HASH_DIGEST_LENGTH());
2519 /* Change the HASH state */
2520 hhash
->State
= HAL_HASH_STATE_READY
;
2522 /* Reset HASH state machine */
2523 hhash
->Phase
= HAL_HASH_PHASE_READY
;
2527 /* Process Unlocked */
2528 __HAL_UNLOCK(hhash
);
2530 /* Return function status */
2542 * @brief If not already done, initialize the HASH peripheral then
2543 * processes pInBuffer.
2544 * @note Field hhash->Phase of HASH handle is tested to check whether or not
2545 * the Peripheral has already been initialized.
2546 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2547 * HASH digest computation is corrupted.
2548 * @param hhash HASH handle.
2549 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
2550 * @param Size length of the input buffer in bytes, must be a multiple of 4.
2551 * @param Algorithm HASH algorithm.
2552 * @retval HAL status
2554 HAL_StatusTypeDef
HASH_Accumulate(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint32_t Algorithm
)
2556 uint8_t *pInBuffer_tmp
; /* input data address, input parameter of HASH_WriteData() */
2557 uint32_t Size_tmp
; /* input data size (in bytes), input parameter of HASH_WriteData() */
2558 HAL_HASH_StateTypeDef State_tmp
= hhash
->State
;
2560 /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2561 if ((Size
% 4U) != 0U)
2566 /* Initiate HASH processing in case of start or resumption */
2567 if((State_tmp
== HAL_HASH_STATE_READY
) || (State_tmp
== HAL_HASH_STATE_SUSPENDED
))
2569 /* Check input parameters */
2570 if ((pInBuffer
== NULL
) || (Size
== 0U))
2572 hhash
->State
= HAL_HASH_STATE_READY
;
2576 /* Process Locked */
2579 /* If resuming the HASH processing */
2580 if (hhash
->State
== HAL_HASH_STATE_SUSPENDED
)
2582 /* Change the HASH state */
2583 hhash
->State
= HAL_HASH_STATE_BUSY
;
2585 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2586 to the API input parameters but to those saved beforehand by HASH_WriteData()
2587 when the processing was suspended */
2588 pInBuffer_tmp
= hhash
->pHashInBuffPtr
; /* pInBuffer_tmp is set to the input data address */
2589 Size_tmp
= hhash
->HashInCount
; /* Size_tmp contains the input data size in bytes */
2594 /* Change the HASH state */
2595 hhash
->State
= HAL_HASH_STATE_BUSY
;
2597 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2598 input parameters of HASH_WriteData() */
2599 pInBuffer_tmp
= pInBuffer
; /* pInBuffer_tmp is set to the input data address */
2600 Size_tmp
= Size
; /* Size_tmp contains the input data size in bytes */
2602 /* Check if initialization phase has already be performed */
2603 if(hhash
->Phase
== HAL_HASH_PHASE_READY
)
2605 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2606 MODIFY_REG(HASH
->CR
, HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_CR_INIT
);
2610 hhash
->Phase
= HAL_HASH_PHASE_PROCESS
;
2614 /* Write input buffer in Data register */
2615 hhash
->Status
= HASH_WriteData(hhash
, pInBuffer_tmp
, Size_tmp
);
2616 if (hhash
->Status
!= HAL_OK
)
2618 return hhash
->Status
;
2621 /* If the process has not been suspended, move the state to Ready */
2622 if (hhash
->State
!= HAL_HASH_STATE_SUSPENDED
)
2624 /* Change the HASH state */
2625 hhash
->State
= HAL_HASH_STATE_READY
;
2628 /* Process Unlocked */
2629 __HAL_UNLOCK(hhash
);
2631 /* Return function status */
2645 * @brief If not already done, initialize the HASH peripheral then
2646 * processes pInBuffer in interruption mode.
2647 * @note Field hhash->Phase of HASH handle is tested to check whether or not
2648 * the Peripheral has already been initialized.
2649 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2650 * HASH digest computation is corrupted.
2651 * @param hhash HASH handle.
2652 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
2653 * @param Size length of the input buffer in bytes, must be a multiple of 4.
2654 * @param Algorithm HASH algorithm.
2655 * @retval HAL status
2657 HAL_StatusTypeDef
HASH_Accumulate_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint32_t Algorithm
)
2659 HAL_HASH_StateTypeDef State_tmp
= hhash
->State
;
2660 __IO
uint32_t inputaddr
= (uint32_t) pInBuffer
;
2661 uint32_t SizeVar
= Size
;
2663 /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2664 if ((Size
% 4U) != 0U)
2669 /* Initiate HASH processing in case of start or resumption */
2670 if((State_tmp
== HAL_HASH_STATE_READY
) || (State_tmp
== HAL_HASH_STATE_SUSPENDED
))
2672 /* Check input parameters */
2673 if ((pInBuffer
== NULL
) || (Size
== 0U))
2675 hhash
->State
= HAL_HASH_STATE_READY
;
2679 /* Process Locked */
2682 /* If resuming the HASH processing */
2683 if (hhash
->State
== HAL_HASH_STATE_SUSPENDED
)
2685 /* Change the HASH state */
2686 hhash
->State
= HAL_HASH_STATE_BUSY
;
2690 /* Change the HASH state */
2691 hhash
->State
= HAL_HASH_STATE_BUSY
;
2693 /* Check if initialization phase has already be performed */
2694 if(hhash
->Phase
== HAL_HASH_PHASE_READY
)
2696 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2697 MODIFY_REG(HASH
->CR
, HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_CR_INIT
);
2698 hhash
->HashITCounter
= 1;
2702 hhash
->HashITCounter
= 3; /* 'cruise-speed' reached during a previous buffer processing */
2706 hhash
->Phase
= HAL_HASH_PHASE_PROCESS
;
2708 /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2709 fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2710 Therefore, first words are manually entered until DINIS raises, or until there
2711 is not more data to enter. */
2712 while((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS
))) && (SizeVar
> 0U))
2715 /* Write input data 4 bytes at a time */
2716 HASH
->DIN
= *(uint32_t*)inputaddr
;
2721 /* If DINIS is still not set or if all the data have been fed, stop here */
2722 if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS
))) || (SizeVar
== 0U))
2724 /* Change the HASH state */
2725 hhash
->State
= HAL_HASH_STATE_READY
;
2727 /* Process Unlock */
2728 __HAL_UNLOCK(hhash
);
2730 /* Return function status */
2734 /* otherwise, carry on in interrupt-mode */
2735 hhash
->HashInCount
= SizeVar
; /* Counter used to keep track of number of data
2736 to be fed to the Peripheral */
2737 hhash
->pHashInBuffPtr
= (uint8_t *)inputaddr
; /* Points at data which will be fed to the Peripheral at
2738 the next interruption */
2739 /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2740 the information describing where the HASH process is stopped.
2741 These variables are used later on to resume the HASH processing at the
2742 correct location. */
2746 /* Set multi buffers accumulation flag */
2747 hhash
->Accumulation
= 1U;
2749 /* Process Unlock */
2750 __HAL_UNLOCK(hhash
);
2752 /* Enable Data Input interrupt */
2753 __HAL_HASH_ENABLE_IT(HASH_IT_DINI
);
2755 /* Return function status */
2769 * @brief Initialize the HASH peripheral, next process pInBuffer then
2770 * read the computed digest in interruption mode.
2771 * @note Digest is available in pOutBuffer.
2772 * @param hhash HASH handle.
2773 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
2774 * @param Size length of the input buffer in bytes.
2775 * @param pOutBuffer pointer to the computed digest.
2776 * @param Algorithm HASH algorithm.
2777 * @retval HAL status
2779 HAL_StatusTypeDef
HASH_Start_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Algorithm
)
2781 HAL_HASH_StateTypeDef State_tmp
= hhash
->State
;
2782 __IO
uint32_t inputaddr
= (uint32_t) pInBuffer
;
2783 uint32_t polling_step
= 0U;
2784 uint32_t initialization_skipped
= 0U;
2785 uint32_t SizeVar
= Size
;
2787 /* If State is ready or suspended, start or resume IT-based HASH processing */
2788 if((State_tmp
== HAL_HASH_STATE_READY
) || (State_tmp
== HAL_HASH_STATE_SUSPENDED
))
2790 /* Check input parameters */
2791 if ((pInBuffer
== NULL
) || (Size
== 0U) || (pOutBuffer
== NULL
))
2793 hhash
->State
= HAL_HASH_STATE_READY
;
2797 /* Process Locked */
2800 /* Change the HASH state */
2801 hhash
->State
= HAL_HASH_STATE_BUSY
;
2803 /* Initialize IT counter */
2804 hhash
->HashITCounter
= 1;
2806 /* Check if initialization phase has already be performed */
2807 if(hhash
->Phase
== HAL_HASH_PHASE_READY
)
2809 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2810 MODIFY_REG(HASH
->CR
, HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_CR_INIT
);
2812 /* Configure the number of valid bits in last word of the message */
2813 __HAL_HASH_SET_NBVALIDBITS(SizeVar
);
2816 hhash
->HashInCount
= SizeVar
; /* Counter used to keep track of number of data
2817 to be fed to the Peripheral */
2818 hhash
->pHashInBuffPtr
= pInBuffer
; /* Points at data which will be fed to the Peripheral at
2819 the next interruption */
2820 /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2821 the information describing where the HASH process is stopped.
2822 These variables are used later on to resume the HASH processing at the
2823 correct location. */
2825 hhash
->pHashOutBuffPtr
= pOutBuffer
; /* Points at the computed digest */
2829 initialization_skipped
= 1; /* info user later on in case of multi-buffer */
2833 hhash
->Phase
= HAL_HASH_PHASE_PROCESS
;
2835 /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2836 fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2837 Therefore, first words are manually entered until DINIS raises. */
2838 while((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS
))) && (SizeVar
> 3U))
2840 polling_step
= 1U; /* note that some words are entered before enabling the interrupt */
2842 /* Write input data 4 bytes at a time */
2843 HASH
->DIN
= *(uint32_t*)inputaddr
;
2848 if (polling_step
== 1U)
2852 /* If all the data have been entered at this point, it only remains to
2854 hhash
->pHashOutBuffPtr
= pOutBuffer
; /* Points at the computed digest */
2856 /* Start the Digest calculation */
2857 __HAL_HASH_START_DIGEST();
2858 /* Process Unlock */
2859 __HAL_UNLOCK(hhash
);
2861 /* Enable Interrupts */
2862 __HAL_HASH_ENABLE_IT(HASH_IT_DCI
);
2864 /* Return function status */
2867 else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS
))
2869 /* It remains data to enter and the Peripheral is ready to trigger DINIE,
2871 Update HashInCount and pHashInBuffPtr accordingly. */
2872 hhash
->HashInCount
= SizeVar
;
2873 hhash
->pHashInBuffPtr
= (uint8_t *)inputaddr
;
2874 __HAL_HASH_SET_NBVALIDBITS(SizeVar
); /* Update the configuration of the number of valid bits in last word of the message */
2875 hhash
->pHashOutBuffPtr
= pOutBuffer
; /* Points at the computed digest */
2876 if (initialization_skipped
== 1U)
2878 hhash
->HashITCounter
= 3; /* 'cruise-speed' reached during a previous buffer processing */
2883 /* DINIS is not set but it remains a few data to enter (not enough for a full word).
2884 Manually enter the last bytes before enabling DCIE. */
2885 __HAL_HASH_SET_NBVALIDBITS(SizeVar
);
2886 HASH
->DIN
= *(uint32_t*)inputaddr
;
2888 /* Start the Digest calculation */
2889 hhash
->pHashOutBuffPtr
= pOutBuffer
; /* Points at the computed digest */
2890 __HAL_HASH_START_DIGEST();
2891 /* Process Unlock */
2892 __HAL_UNLOCK(hhash
);
2894 /* Enable Interrupts */
2895 __HAL_HASH_ENABLE_IT(HASH_IT_DCI
);
2897 /* Return function status */
2900 } /* if (polling_step == 1) */
2903 /* Process Unlock */
2904 __HAL_UNLOCK(hhash
);
2906 /* Enable Interrupts */
2907 __HAL_HASH_ENABLE_IT(HASH_IT_DINI
|HASH_IT_DCI
);
2909 /* Return function status */
2921 * @brief Initialize the HASH peripheral then initiate a DMA transfer
2922 * to feed the input buffer to the Peripheral.
2923 * @note If MDMAT bit is set before calling this function (multi-buffer
2924 * HASH processing case), the input buffer size (in bytes) must be
2925 * a multiple of 4 otherwise, the HASH digest computation is corrupted.
2926 * For the processing of the last buffer of the thread, MDMAT bit must
2927 * be reset and the buffer length (in bytes) doesn't have to be a
2929 * @param hhash HASH handle.
2930 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
2931 * @param Size length of the input buffer in bytes.
2932 * @param Algorithm HASH algorithm.
2933 * @retval HAL status
2935 HAL_StatusTypeDef
HASH_Start_DMA(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint32_t Algorithm
)
2939 HAL_StatusTypeDef status
;
2940 HAL_HASH_StateTypeDef State_tmp
= hhash
->State
;
2943 /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
2944 (case of multi-buffer HASH processing) */
2945 assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size
));
2947 /* If State is ready or suspended, start or resume polling-based HASH processing */
2948 if((State_tmp
== HAL_HASH_STATE_READY
) || (State_tmp
== HAL_HASH_STATE_SUSPENDED
))
2950 /* Check input parameters */
2951 if ( (pInBuffer
== NULL
) || (Size
== 0U) ||
2952 /* Check phase coherency. Phase must be
2953 either READY (fresh start)
2954 or PROCESS (multi-buffer HASH management) */
2955 ((hhash
->Phase
!= HAL_HASH_PHASE_READY
) && (!(IS_HASH_PROCESSING(hhash
)))))
2957 hhash
->State
= HAL_HASH_STATE_READY
;
2962 /* Process Locked */
2965 /* If not a resumption case */
2966 if (hhash
->State
== HAL_HASH_STATE_READY
)
2968 /* Change the HASH state */
2969 hhash
->State
= HAL_HASH_STATE_BUSY
;
2971 /* Check if initialization phase has already been performed.
2972 If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
2973 API is processing a new input data message in case of multi-buffer HASH
2975 if(hhash
->Phase
== HAL_HASH_PHASE_READY
)
2977 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2978 MODIFY_REG(HASH
->CR
, HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_CR_INIT
);
2981 hhash
->Phase
= HAL_HASH_PHASE_PROCESS
;
2984 /* Configure the Number of valid bits in last word of the message */
2985 __HAL_HASH_SET_NBVALIDBITS(Size
);
2987 inputaddr
= (uint32_t)pInBuffer
; /* DMA transfer start address */
2988 inputSize
= Size
; /* DMA transfer size (in bytes) */
2990 /* In case of suspension request, save the starting parameters */
2991 hhash
->pHashInBuffPtr
= pInBuffer
; /* DMA transfer start address */
2992 hhash
->HashInCount
= Size
; /* DMA transfer size (in bytes) */
2995 /* If resumption case */
2998 /* Change the HASH state */
2999 hhash
->State
= HAL_HASH_STATE_BUSY
;
3001 /* Resumption case, inputaddr and inputSize are not set to the API input parameters
3002 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3003 processing was suspended */
3004 inputaddr
= (uint32_t)hhash
->pHashInBuffPtr
; /* DMA transfer start address */
3005 inputSize
= hhash
->HashInCount
; /* DMA transfer size (in bytes) */
3009 /* Set the HASH DMA transfert complete callback */
3010 hhash
->hdmain
->XferCpltCallback
= HASH_DMAXferCplt
;
3011 /* Set the DMA error callback */
3012 hhash
->hdmain
->XferErrorCallback
= HASH_DMAError
;
3014 /* Store number of words already pushed to manage proper DMA processing suspension */
3015 hhash
->NbWordsAlreadyPushed
= HASH_NBW_PUSHED();
3017 /* Enable the DMA In DMA Stream */
3018 status
= HAL_DMA_Start_IT(hhash
->hdmain
, inputaddr
, (uint32_t)&HASH
->DIN
, (((inputSize
%4U)!=0U) ? ((inputSize
+(4U-(inputSize
%4U)))/4U):(inputSize
/4U)));
3020 /* Enable DMA requests */
3021 SET_BIT(HASH
->CR
, HASH_CR_DMAE
);
3023 /* Process Unlock */
3024 __HAL_UNLOCK(hhash
);
3026 /* Return function status */
3027 if (status
!= HAL_OK
)
3029 /* Update HASH state machine to error */
3030 hhash
->State
= HAL_HASH_STATE_ERROR
;
3042 * @brief Return the computed digest.
3043 * @note The API waits for DCIS to be set then reads the computed digest.
3044 * @param hhash HASH handle.
3045 * @param pOutBuffer pointer to the computed digest.
3046 * @param Timeout Timeout value.
3047 * @retval HAL status
3049 HAL_StatusTypeDef
HASH_Finish(HASH_HandleTypeDef
*hhash
, uint8_t* pOutBuffer
, uint32_t Timeout
)
3052 if(hhash
->State
== HAL_HASH_STATE_READY
)
3054 /* Check parameter */
3055 if (pOutBuffer
== NULL
)
3060 /* Process Locked */
3063 /* Change the HASH state to busy */
3064 hhash
->State
= HAL_HASH_STATE_BUSY
;
3066 /* Wait for DCIS flag to be set */
3067 if (HASH_WaitOnFlagUntilTimeout(hhash
, HASH_FLAG_DCIS
, RESET
, Timeout
) != HAL_OK
)
3072 /* Read the message digest */
3073 HASH_GetDigest(pOutBuffer
, HASH_DIGEST_LENGTH());
3075 /* Change the HASH state to ready */
3076 hhash
->State
= HAL_HASH_STATE_READY
;
3078 /* Reset HASH state machine */
3079 hhash
->Phase
= HAL_HASH_PHASE_READY
;
3081 /* Process UnLock */
3082 __HAL_UNLOCK(hhash
);
3084 /* Return function status */
3097 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3098 * read the computed digest.
3099 * @note Digest is available in pOutBuffer.
3100 * @note Same key is used for the inner and the outer hash functions; pointer to key and
3101 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3102 * @param hhash HASH handle.
3103 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
3104 * @param Size length of the input buffer in bytes.
3105 * @param pOutBuffer pointer to the computed digest.
3106 * @param Timeout Timeout value.
3107 * @param Algorithm HASH algorithm.
3108 * @retval HAL status
3110 HAL_StatusTypeDef
HMAC_Start(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Timeout
, uint32_t Algorithm
)
3112 HAL_HASH_StateTypeDef State_tmp
= hhash
->State
;
3114 /* If State is ready or suspended, start or resume polling-based HASH processing */
3115 if((State_tmp
== HAL_HASH_STATE_READY
) || (State_tmp
== HAL_HASH_STATE_SUSPENDED
))
3117 /* Check input parameters */
3118 if ((pInBuffer
== NULL
) || (Size
== 0U) || (hhash
->Init
.pKey
== NULL
) || (hhash
->Init
.KeySize
== 0U) || (pOutBuffer
== NULL
))
3120 hhash
->State
= HAL_HASH_STATE_READY
;
3124 /* Process Locked */
3127 /* Change the HASH state */
3128 hhash
->State
= HAL_HASH_STATE_BUSY
;
3130 /* Check if initialization phase has already be performed */
3131 if(hhash
->Phase
== HAL_HASH_PHASE_READY
)
3133 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3134 if(hhash
->Init
.KeySize
> 64U)
3136 MODIFY_REG(HASH
->CR
, HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_ALGOMODE_HMAC
| HASH_HMAC_KEYTYPE_LONGKEY
| HASH_CR_INIT
);
3140 MODIFY_REG(HASH
->CR
, HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_ALGOMODE_HMAC
| HASH_CR_INIT
);
3142 /* Set the phase to Step 1 */
3143 hhash
->Phase
= HAL_HASH_PHASE_HMAC_STEP_1
;
3144 /* Resort to hhash internal fields to feed the Peripheral.
3145 Parameters will be updated in case of suspension to contain the proper
3146 information at resumption time. */
3147 hhash
->pHashOutBuffPtr
= pOutBuffer
; /* Output digest address */
3148 hhash
->pHashInBuffPtr
= pInBuffer
; /* Input data address, HMAC_Processing input parameter for Step 2 */
3149 hhash
->HashInCount
= Size
; /* Input data size, HMAC_Processing input parameter for Step 2 */
3150 hhash
->HashBuffSize
= Size
; /* Store the input buffer size for the whole HMAC process */
3151 hhash
->pHashKeyBuffPtr
= hhash
->Init
.pKey
; /* Key address, HMAC_Processing input parameter for Step 1 and Step 3 */
3152 hhash
->HashKeyCount
= hhash
->Init
.KeySize
; /* Key size, HMAC_Processing input parameter for Step 1 and Step 3 */
3155 /* Carry out HMAC processing */
3156 return HMAC_Processing(hhash
, Timeout
);
3168 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3169 * read the computed digest in interruption mode.
3170 * @note Digest is available in pOutBuffer.
3171 * @note Same key is used for the inner and the outer hash functions; pointer to key and
3172 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3173 * @param hhash HASH handle.
3174 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
3175 * @param Size length of the input buffer in bytes.
3176 * @param pOutBuffer pointer to the computed digest.
3177 * @param Algorithm HASH algorithm.
3178 * @retval HAL status
3180 HAL_StatusTypeDef
HMAC_Start_IT(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint8_t* pOutBuffer
, uint32_t Algorithm
)
3182 HAL_HASH_StateTypeDef State_tmp
= hhash
->State
;
3184 /* If State is ready or suspended, start or resume IT-based HASH processing */
3185 if((State_tmp
== HAL_HASH_STATE_READY
) || (State_tmp
== HAL_HASH_STATE_SUSPENDED
))
3187 /* Check input parameters */
3188 if ((pInBuffer
== NULL
) || (Size
== 0U) || (hhash
->Init
.pKey
== NULL
) || (hhash
->Init
.KeySize
== 0U) || (pOutBuffer
== NULL
))
3190 hhash
->State
= HAL_HASH_STATE_READY
;
3194 /* Process Locked */
3197 /* Change the HASH state */
3198 hhash
->State
= HAL_HASH_STATE_BUSY
;
3200 /* Initialize IT counter */
3201 hhash
->HashITCounter
= 1;
3203 /* Check if initialization phase has already be performed */
3204 if (hhash
->Phase
== HAL_HASH_PHASE_READY
)
3206 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3207 if(hhash
->Init
.KeySize
> 64U)
3209 MODIFY_REG(HASH
->CR
, HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_ALGOMODE_HMAC
| HASH_HMAC_KEYTYPE_LONGKEY
| HASH_CR_INIT
);
3213 MODIFY_REG(HASH
->CR
, HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_ALGOMODE_HMAC
| HASH_CR_INIT
);
3216 /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
3217 to feed the Peripheral whatever the HMAC step.
3218 Lines below are set to start HMAC Step 1 processing where key is entered first. */
3219 hhash
->HashInCount
= hhash
->Init
.KeySize
; /* Key size */
3220 hhash
->pHashInBuffPtr
= hhash
->Init
.pKey
; /* Key address */
3222 /* Store input and output parameters in handle fields to manage steps transition
3223 or possible HMAC suspension/resumption */
3224 hhash
->pHashKeyBuffPtr
= hhash
->Init
.pKey
; /* Key address */
3225 hhash
->pHashMsgBuffPtr
= pInBuffer
; /* Input message address */
3226 hhash
->HashBuffSize
= Size
; /* Input message size (in bytes) */
3227 hhash
->pHashOutBuffPtr
= pOutBuffer
; /* Output digest address */
3229 /* Configure the number of valid bits in last word of the key */
3230 __HAL_HASH_SET_NBVALIDBITS(hhash
->Init
.KeySize
);
3232 /* Set the phase to Step 1 */
3233 hhash
->Phase
= HAL_HASH_PHASE_HMAC_STEP_1
;
3235 else if ((hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_1
) || (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_3
))
3237 /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
3240 else if (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_2
)
3242 /* Restart IT-based HASH processing after Step 2 suspension */
3247 /* Error report as phase incorrect */
3248 /* Process Unlock */
3249 __HAL_UNLOCK(hhash
);
3250 hhash
->State
= HAL_HASH_STATE_READY
;
3254 /* Process Unlock */
3255 __HAL_UNLOCK(hhash
);
3257 /* Enable Interrupts */
3258 __HAL_HASH_ENABLE_IT(HASH_IT_DINI
|HASH_IT_DCI
);
3260 /* Return function status */
3273 * @brief Initialize the HASH peripheral in HMAC mode then initiate the required
3274 * DMA transfers to feed the key and the input buffer to the Peripheral.
3275 * @note Same key is used for the inner and the outer hash functions; pointer to key and
3276 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3277 * @note In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
3278 * be a multiple of 4 otherwise, the HASH digest computation is corrupted.
3279 * Only the length of the last buffer of the thread doesn't have to be a
3281 * @param hhash HASH handle.
3282 * @param pInBuffer pointer to the input buffer (buffer to be hashed).
3283 * @param Size length of the input buffer in bytes.
3284 * @param Algorithm HASH algorithm.
3285 * @retval HAL status
3287 HAL_StatusTypeDef
HMAC_Start_DMA(HASH_HandleTypeDef
*hhash
, uint8_t *pInBuffer
, uint32_t Size
, uint32_t Algorithm
)
3291 HAL_StatusTypeDef status
;
3292 HAL_HASH_StateTypeDef State_tmp
= hhash
->State
;
3293 /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
3294 is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
3295 assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash
, Size
));
3296 /* If State is ready or suspended, start or resume DMA-based HASH processing */
3297 if((State_tmp
== HAL_HASH_STATE_READY
) || (State_tmp
== HAL_HASH_STATE_SUSPENDED
))
3299 /* Check input parameters */
3300 if ((pInBuffer
== NULL
) || (Size
== 0U) || (hhash
->Init
.pKey
== NULL
) || (hhash
->Init
.KeySize
== 0U) ||
3301 /* Check phase coherency. Phase must be
3302 either READY (fresh start)
3303 or one of HMAC PROCESS steps (multi-buffer HASH management) */
3304 ((hhash
->Phase
!= HAL_HASH_PHASE_READY
) && (!(IS_HMAC_PROCESSING(hhash
)))))
3306 hhash
->State
= HAL_HASH_STATE_READY
;
3311 /* Process Locked */
3314 /* If not a case of resumption after suspension */
3315 if (hhash
->State
== HAL_HASH_STATE_READY
)
3317 /* Check whether or not initialization phase has already be performed */
3318 if(hhash
->Phase
== HAL_HASH_PHASE_READY
)
3320 /* Change the HASH state */
3321 hhash
->State
= HAL_HASH_STATE_BUSY
;
3322 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
3323 At the same time, ensure MDMAT bit is cleared. */
3324 if(hhash
->Init
.KeySize
> 64U)
3326 MODIFY_REG(HASH
->CR
, HASH_CR_MDMAT
|HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_ALGOMODE_HMAC
| HASH_HMAC_KEYTYPE_LONGKEY
| HASH_CR_INIT
);
3330 MODIFY_REG(HASH
->CR
, HASH_CR_MDMAT
|HASH_CR_LKEY
|HASH_CR_ALGO
|HASH_CR_MODE
|HASH_CR_INIT
, Algorithm
| HASH_ALGOMODE_HMAC
| HASH_CR_INIT
);
3332 /* Store input aparameters in handle fields to manage steps transition
3333 or possible HMAC suspension/resumption */
3334 hhash
->HashInCount
= hhash
->Init
.KeySize
; /* Initial size for first DMA transfer (key size) */
3335 hhash
->pHashKeyBuffPtr
= hhash
->Init
.pKey
; /* Key address */
3336 hhash
->pHashInBuffPtr
= hhash
->Init
.pKey
; /* First address passed to DMA (key address at Step 1) */
3337 hhash
->pHashMsgBuffPtr
= pInBuffer
; /* Input data address */
3338 hhash
->HashBuffSize
= Size
; /* input data size (in bytes) */
3340 /* Set DMA input parameters */
3341 inputaddr
= (uint32_t)(hhash
->Init
.pKey
); /* Address passed to DMA (start by entering Key message) */
3342 inputSize
= hhash
->Init
.KeySize
; /* Size for first DMA transfer (in bytes) */
3344 /* Configure the number of valid bits in last word of the key */
3345 __HAL_HASH_SET_NBVALIDBITS(hhash
->Init
.KeySize
);
3347 /* Set the phase to Step 1 */
3348 hhash
->Phase
= HAL_HASH_PHASE_HMAC_STEP_1
;
3351 else if (hhash
->Phase
== HAL_HASH_PHASE_HMAC_STEP_2
)
3353 /* Process a new input data message in case of multi-buffer HMAC processing
3354 (this is not a resumption case) */
3356 /* Change the HASH state */
3357 hhash
->State
= HAL_HASH_STATE_BUSY
;
3359 /* Save input parameters to be able to manage possible suspension/resumption */
3360 hhash
->HashInCount
= Size
; /* Input message address */
3361 hhash
->pHashInBuffPtr
= pInBuffer
; /* Input message size in bytes */
3363 /* Set DMA input parameters */
3364 inputaddr
= (uint32_t)pInBuffer
; /* Input message address */
3365 inputSize
= Size
; /* Input message size in bytes */
3367 if (hhash
->DigestCalculationDisable
== RESET
)
3369 /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
3370 __HAL_HASH_RESET_MDMAT();
3371 __HAL_HASH_SET_NBVALIDBITS(inputSize
);
3376 /* Phase not aligned with handle READY state */
3377 __HAL_UNLOCK(hhash
);
3378 /* Return function status */
3384 /* Resumption case (phase may be Step 1, 2 or 3) */
3386 /* Change the HASH state */
3387 hhash
->State
= HAL_HASH_STATE_BUSY
;
3389 /* Set DMA input parameters at resumption location;
3390 inputaddr and inputSize are not set to the API input parameters
3391 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3392 processing was suspended. */
3393 inputaddr
= (uint32_t)(hhash
->pHashInBuffPtr
); /* Input message address */
3394 inputSize
= hhash
->HashInCount
; /* Input message size in bytes */
3398 /* Set the HASH DMA transfert complete callback */
3399 hhash
->hdmain
->XferCpltCallback
= HASH_DMAXferCplt
;
3400 /* Set the DMA error callback */
3401 hhash
->hdmain
->XferErrorCallback
= HASH_DMAError
;
3403 /* Store number of words already pushed to manage proper DMA processing suspension */
3404 hhash
->NbWordsAlreadyPushed
= HASH_NBW_PUSHED();
3406 /* Enable the DMA In DMA Stream */
3407 status
= HAL_DMA_Start_IT(hhash
->hdmain
, inputaddr
, (uint32_t)&HASH
->DIN
, (((inputSize
%4U)!=0U) ? ((inputSize
+(4U-(inputSize
%4U)))/4U):(inputSize
/4U)));
3408 /* Enable DMA requests */
3409 SET_BIT(HASH
->CR
, HASH_CR_DMAE
);
3411 /* Process Unlocked */
3412 __HAL_UNLOCK(hhash
);
3414 /* Return function status */
3415 if (status
!= HAL_OK
)
3417 /* Update HASH state machine to error */
3418 hhash
->State
= HAL_HASH_STATE_ERROR
;
3421 /* Return function status */
3433 #endif /* HAL_HASH_MODULE_ENABLED */
3445 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/