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