source: S-port/trunk/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c@ 1

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