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