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