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