1 /**
2   ******************************************************************************
3   * @file    stm32f7xx_hal_hash_ex.c
4   * @author  MCD Application Team
5   * @version V1.0.1
6   * @date    25-June-2015
7   * @brief   HASH HAL Extension module driver.
8   *          This file provides firmware functions to manage the following
9   *          functionalities of HASH peripheral:
10   *           + Extended HASH processing functions based on SHA224 Algorithm
11   *           + Extended HASH processing functions based on SHA256 Algorithm
12   *
13   @verbatim
14   ==============================================================================
15                      ##### How to use this driver #####
16   ==============================================================================
17     [..]
18     The HASH HAL driver can be used as follows:
19     (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit():
20         (##) Enable the HASH interface clock using __HAL_RCC_HASH_CLK_ENABLE()
21         (##) In case of using processing APIs based on interrupts (e.g. HAL_HMACEx_SHA224_Start())
22             (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority()
23             (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ()
24             (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler()
25         (##) In case of using DMA to control data transfer (e.g. HAL_HMACEx_SH224_Start_DMA())
26             (+++) Enable the DMAx interface clock using __DMAx_CLK_ENABLE()
27             (+++) Configure and enable one DMA stream one for managing data transfer from
28                 memory to peripheral (input stream). Managing data transfer from
29                 peripheral to memory can be performed only using CPU
30             (+++) Associate the initialized DMA handle to the HASH DMA handle
31                 using  __HAL_LINKDMA()
32             (+++) Configure the priority and enable the NVIC for the transfer complete
33                 interrupt on the DMA Stream: HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ()
34     (#)Initialize the HASH HAL using HAL_HASH_Init(). This function configures mainly:
35         (##) The data type: 1-bit, 8-bit, 16-bit and 32-bit.
36         (##) For HMAC, the encryption key.
37         (##) For HMAC, the key size used for encryption.
38     (#)Three processing functions are available:
39         (##) Polling mode: processing APIs are blocking functions
40              i.e. they process the data and wait till the digest computation is finished
41              e.g. HAL_HASHEx_SHA224_Start()
42         (##) Interrupt mode: encryption and decryption APIs are not blocking functions
43                 i.e. they process the data under interrupt
44                 e.g. HAL_HASHEx_SHA224_Start_IT()
45         (##) DMA mode: processing APIs are not blocking functions and the CPU is
46              not used for data transfer i.e. the data transfer is ensured by DMA
47                 e.g. HAL_HASHEx_SHA224_Start_DMA()
48     (#)When the processing function is called at first time after HAL_HASH_Init()
49        the HASH peripheral is initialized and processes the buffer in input.
50        After that, the digest computation is started.
51        When processing multi-buffer use the accumulate function to write the
52        data in the peripheral without starting the digest computation. In last
53        buffer use the start function to input the last buffer ans start the digest
54        computation.
55        (##) e.g. HAL_HASHEx_SHA224_Accumulate() : write 1st data buffer in the peripheral without starting the digest computation
56        (##)  write (n-1)th data buffer in the peripheral without starting the digest computation
57        (##)  HAL_HASHEx_SHA224_Start() : write (n)th data buffer in the peripheral and start the digest computation
58     (#)In HMAC mode, there is no Accumulate API. Only Start API is available.
59     (#)In case of using DMA, call the DMA start processing e.g. HAL_HASHEx_SHA224_Start_DMA().
60        After that, call the finish function in order to get the digest value
61        e.g. HAL_HASHEx_SHA224_Finish()
62     (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
63 
64   @endverbatim
65   ******************************************************************************
66   * @attention
67   *
68   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
69   *
70   * Redistribution and use in source and binary forms, with or without modification,
71   * are permitted provided that the following conditions are met:
72   *   1. Redistributions of source code must retain the above copyright notice,
73   *      this list of conditions and the following disclaimer.
74   *   2. Redistributions in binary form must reproduce the above copyright notice,
75   *      this list of conditions and the following disclaimer in the documentation
76   *      and/or other materials provided with the distribution.
77   *   3. Neither the name of STMicroelectronics nor the names of its contributors
78   *      may be used to endorse or promote products derived from this software
79   *      without specific prior written permission.
80   *
81   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
82   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
84   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
85   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
87   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
88   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
89   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
90   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
91   *
92   ******************************************************************************
93   */
94 
95 /* Includes ------------------------------------------------------------------*/
96 #include "stm32f7xx_hal.h"
97 
98 /** @addtogroup STM32F7xx_HAL_Driver
99   * @{
100   */
101 #if defined(STM32F756xx)
102 
103 /** @defgroup HASHEx HASHEx
104   * @brief HASH Extension HAL module driver.
105   * @{
106   */
107 
108 #ifdef HAL_HASH_MODULE_ENABLED
109 
110 /* Private typedef -----------------------------------------------------------*/
111 /* Private define ------------------------------------------------------------*/
112 /* Private macro -------------------------------------------------------------*/
113 /* Private variables ---------------------------------------------------------*/
114 /* Private function prototypes -----------------------------------------------*/
115 /** @addtogroup HASHEx_Private_Functions
116   * @{
117   */
118 static void HASHEx_DMAXferCplt(DMA_HandleTypeDef *hdma);
119 static void HASHEx_WriteData(uint8_t *pInBuffer, uint32_t Size);
120 static void HASHEx_GetDigest(uint8_t *pMsgDigest, uint8_t Size);
121 static void HASHEx_DMAError(DMA_HandleTypeDef *hdma);
122 /**
123   * @}
124   */
125 
126 /* Private functions ---------------------------------------------------------*/
127 
128 /** @addtogroup HASHEx_Private_Functions
129   * @{
130   */
131 
132 /**
133   * @brief  Writes the input buffer in data register.
134   * @param  pInBuffer: Pointer to input buffer
135   * @param  Size: The size of input buffer
136   * @retval None
137   */
HASHEx_WriteData(uint8_t * pInBuffer,uint32_t Size)138 static void HASHEx_WriteData(uint8_t *pInBuffer, uint32_t Size)
139 {
140     uint32_t buffercounter;
141     uint32_t inputaddr = (uint32_t) pInBuffer;
142 
143     for (buffercounter = 0; buffercounter < Size; buffercounter+=4) {
144         HASH->DIN = *(uint32_t*)inputaddr;
145         inputaddr+=4;
146     }
147 }
148 
149 /**
150   * @brief  Provides the message digest result.
151   * @param  pMsgDigest: Pointer to the message digest
152   * @param  Size: The size of the message digest in bytes
153   * @retval None
154   */
HASHEx_GetDigest(uint8_t * pMsgDigest,uint8_t Size)155 static void HASHEx_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
156 {
157     uint32_t msgdigest = (uint32_t)pMsgDigest;
158 
159     switch (Size) {
160         case 16:
161             /* Read the message digest */
162             *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
163             msgdigest+=4;
164             *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
165             msgdigest+=4;
166             *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
167             msgdigest+=4;
168             *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
169             break;
170         case 20:
171             /* Read the message digest */
172             *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
173             msgdigest+=4;
174             *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
175             msgdigest+=4;
176             *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
177             msgdigest+=4;
178             *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
179             msgdigest+=4;
180             *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
181             break;
182         case 28:
183             /* Read the message digest */
184             *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
185             msgdigest+=4;
186             *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
187             msgdigest+=4;
188             *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
189             msgdigest+=4;
190             *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
191             msgdigest+=4;
192             *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
193             msgdigest+=4;
194             *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
195             msgdigest+=4;
196             *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
197             break;
198         case 32:
199             /* Read the message digest */
200             *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
201             msgdigest+=4;
202             *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
203             msgdigest+=4;
204             *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
205             msgdigest+=4;
206             *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
207             msgdigest+=4;
208             *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
209             msgdigest+=4;
210             *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
211             msgdigest+=4;
212             *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
213             msgdigest+=4;
214             *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
215             break;
216         default:
217             break;
218     }
219 }
220 
221 /**
222   * @brief  DMA HASH Input Data complete callback.
223   * @param  hdma: DMA handle
224   * @retval None
225   */
HASHEx_DMAXferCplt(DMA_HandleTypeDef * hdma)226 static void HASHEx_DMAXferCplt(DMA_HandleTypeDef *hdma)
227 {
228     HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
229     uint32_t inputaddr = 0;
230     uint32_t buffersize = 0;
231 
232     if ((HASH->CR & HASH_CR_MODE) != HASH_CR_MODE) {
233         /* Disable the DMA transfer */
234         HASH->CR &= (uint32_t)(~HASH_CR_DMAE);
235 
236         /* Change HASH peripheral state */
237         hhash->State = HAL_HASH_STATE_READY;
238 
239         /* Call Input data transfer complete callback */
240         HAL_HASH_InCpltCallback(hhash);
241     } else {
242         /* Increment Interrupt counter */
243         hhash->HashInCount++;
244         /* Disable the DMA transfer before starting the next transfer */
245         HASH->CR &= (uint32_t)(~HASH_CR_DMAE);
246 
247         if (hhash->HashInCount <= 2) {
248             /* In case HashInCount = 1, set the DMA to transfer data to HASH DIN register */
249             if (hhash->HashInCount == 1) {
250                 inputaddr = (uint32_t)hhash->pHashInBuffPtr;
251                 buffersize = hhash->HashBuffSize;
252             }
253             /* In case HashInCount = 2, set the DMA to transfer key to HASH DIN register */
254             else if (hhash->HashInCount == 2) {
255                 inputaddr = (uint32_t)hhash->Init.pKey;
256                 buffersize = hhash->Init.KeySize;
257             }
258             /* Configure the number of valid bits in last word of the message */
259             MODIFY_REG(HASH->STR, HASH_STR_NBLW, 8 * (buffersize % 4));
260 
261             /* Set the HASH DMA transfer complete */
262             hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
263 
264             /* Enable the DMA In DMA Stream */
265             HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (buffersize%4 ? (buffersize+3)/4:buffersize/4));
266 
267             /* Enable DMA requests */
268             HASH->CR |= (HASH_CR_DMAE);
269         } else {
270             /* Disable the DMA transfer */
271             HASH->CR &= (uint32_t)(~HASH_CR_DMAE);
272 
273             /* Reset the InCount */
274             hhash->HashInCount = 0;
275 
276             /* Change HASH peripheral state */
277             hhash->State = HAL_HASH_STATE_READY;
278 
279             /* Call Input data transfer complete callback */
280             HAL_HASH_InCpltCallback(hhash);
281         }
282     }
283 }
284 
285 /**
286   * @brief  DMA HASH communication error callback.
287   * @param  hdma: DMA handle
288   * @retval None
289   */
HASHEx_DMAError(DMA_HandleTypeDef * hdma)290 static void HASHEx_DMAError(DMA_HandleTypeDef *hdma)
291 {
292     HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
293     hhash->State= HAL_HASH_STATE_READY;
294     HAL_HASH_ErrorCallback(hhash);
295 }
296 
297 /**
298  * @}
299  */
300 
301 /* Exported functions --------------------------------------------------------*/
302 /** @addtogroup HASHEx_Exported_Functions
303   * @{
304   */
305 
306 /** @defgroup  HASHEx_Group1 HASH processing functions
307  *  @brief   processing functions using polling mode
308  *
309 @verbatim
310  ===============================================================================
311               ##### HASH processing using polling mode functions #####
312  ===============================================================================
313     [..]  This section provides functions allowing to calculate in polling mode
314           the hash value using one of the following algorithms:
315       (+) SHA224
316       (+) SHA256
317 
318 @endverbatim
319   * @{
320   */
321 
322 /**
323   * @brief  Initializes the HASH peripheral in SHA224 mode
324   *         then processes pInBuffer. The digest is available in pOutBuffer
325   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
326   *         the configuration information for HASH module
327   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
328   * @param  Size: Length of the input buffer in bytes.
329   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
330   * @param  pOutBuffer: Pointer to the computed digest. Its size must be 28 bytes.
331   * @param  Timeout: Specify Timeout value
332   * @retval HAL status
333   */
HAL_HASHEx_SHA224_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)334 HAL_StatusTypeDef HAL_HASHEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
335 {
336     uint32_t tickstart = 0;
337 
338     /* Process Locked */
339     __HAL_LOCK(hhash);
340 
341     /* Change the HASH state */
342     hhash->State = HAL_HASH_STATE_BUSY;
343 
344     /* Check if initialization phase has already been performed */
345     if (hhash->Phase == HAL_HASH_PHASE_READY) {
346         /* Select the SHA224 mode and reset the HASH processor core, so that the HASH will be ready to compute
347            the message digest of a new message */
348         HASH->CR |= HASH_ALGOSELECTION_SHA224 | HASH_CR_INIT;
349     }
350 
351     /* Set the phase */
352     hhash->Phase = HAL_HASH_PHASE_PROCESS;
353 
354     /* Configure the number of valid bits in last word of the message */
355     __HAL_HASH_SET_NBVALIDBITS(Size);
356 
357     /* Write input buffer in data register */
358     HASHEx_WriteData(pInBuffer, Size);
359 
360     /* Start the digest calculation */
361     __HAL_HASH_START_DIGEST();
362 
363     /* Get tick */
364     tickstart = HAL_GetTick();
365 
366     while ((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY) {
367         /* Check for the Timeout */
368         if (Timeout != HAL_MAX_DELAY) {
369             if ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) {
370                 /* Change state */
371                 hhash->State = HAL_HASH_STATE_TIMEOUT;
372 
373                 /* Process Unlocked */
374                 __HAL_UNLOCK(hhash);
375 
376                 return HAL_TIMEOUT;
377             }
378         }
379     }
380 
381     /* Read the message digest */
382     HASHEx_GetDigest(pOutBuffer, 28);
383 
384     /* Change the HASH state */
385     hhash->State = HAL_HASH_STATE_READY;
386 
387     /* Process Unlocked */
388     __HAL_UNLOCK(hhash);
389 
390     /* Return function status */
391     return HAL_OK;
392 }
393 
394 /**
395   * @brief  Initializes the HASH peripheral in SHA256 mode then processes pInBuffer.
396             The digest is available in pOutBuffer.
397   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
398   *         the configuration information for HASH module
399   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
400   * @param  Size: Length of the input buffer in bytes.
401   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
402   * @param  pOutBuffer: Pointer to the computed digest. Its size must be 32 bytes.
403   * @param  Timeout: Specify Timeout value
404   * @retval HAL status
405   */
HAL_HASHEx_SHA256_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)406 HAL_StatusTypeDef HAL_HASHEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
407 {
408     uint32_t tickstart = 0;
409 
410     /* Process Locked */
411     __HAL_LOCK(hhash);
412 
413     /* Change the HASH state */
414     hhash->State = HAL_HASH_STATE_BUSY;
415 
416     /* Check if initialization phase has already been performed */
417     if (hhash->Phase == HAL_HASH_PHASE_READY) {
418         /* Select the SHA256 mode and reset the HASH processor core, so that the HASH will be ready to compute
419            the message digest of a new message */
420         HASH->CR |= HASH_ALGOSELECTION_SHA256 | HASH_CR_INIT;
421     }
422 
423     /* Set the phase */
424     hhash->Phase = HAL_HASH_PHASE_PROCESS;
425 
426     /* Configure the number of valid bits in last word of the message */
427     __HAL_HASH_SET_NBVALIDBITS(Size);
428 
429     /* Write input buffer in data register */
430     HASHEx_WriteData(pInBuffer, Size);
431 
432     /* Start the digest calculation */
433     __HAL_HASH_START_DIGEST();
434 
435     /* Get tick */
436     tickstart = HAL_GetTick();
437 
438     while ((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY) {
439         /* Check for the Timeout */
440         if (Timeout != HAL_MAX_DELAY) {
441             if ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) {
442                 /* Change state */
443                 hhash->State = HAL_HASH_STATE_TIMEOUT;
444 
445                 /* Process Unlocked */
446                 __HAL_UNLOCK(hhash);
447 
448                 return HAL_TIMEOUT;
449             }
450         }
451     }
452 
453     /* Read the message digest */
454     HASHEx_GetDigest(pOutBuffer, 32);
455 
456     /* Change the HASH state */
457     hhash->State = HAL_HASH_STATE_READY;
458 
459     /* Process Unlocked */
460     __HAL_UNLOCK(hhash);
461 
462     /* Return function status */
463     return HAL_OK;
464 }
465 
466 
467 /**
468   * @brief  Initializes the HASH peripheral in SHA224 mode
469   *         then processes pInBuffer. The digest is available in pOutBuffer
470   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
471   *         the configuration information for HASH module
472   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
473   * @param  Size: Length of the input buffer in bytes.
474   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
475   * @retval HAL status
476   */
HAL_HASHEx_SHA224_Accumulate(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)477 HAL_StatusTypeDef HAL_HASHEx_SHA224_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
478 {
479     /* Process Locked */
480     __HAL_LOCK(hhash);
481 
482     /* Change the HASH state */
483     hhash->State = HAL_HASH_STATE_BUSY;
484 
485     /* Check if initialization phase has already been performed */
486     if (hhash->Phase == HAL_HASH_PHASE_READY) {
487         /* Select the SHA224 mode and reset the HASH processor core, so that the HASH will be ready to compute
488            the message digest of a new message */
489         HASH->CR |= HASH_ALGOSELECTION_SHA224 | HASH_CR_INIT;
490     }
491 
492     /* Set the phase */
493     hhash->Phase = HAL_HASH_PHASE_PROCESS;
494 
495     /* Configure the number of valid bits in last word of the message */
496     __HAL_HASH_SET_NBVALIDBITS(Size);
497 
498     /* Write input buffer in data register */
499     HASHEx_WriteData(pInBuffer, Size);
500 
501     /* Change the HASH state */
502     hhash->State = HAL_HASH_STATE_READY;
503 
504     /* Process Unlocked */
505     __HAL_UNLOCK(hhash);
506 
507     /* Return function status */
508     return HAL_OK;
509 }
510 
511 
512 /**
513   * @brief  Initializes the HASH peripheral in SHA256 mode then processes pInBuffer.
514             The digest is available in pOutBuffer.
515   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
516   *         the configuration information for HASH module
517   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
518   * @param  Size: Length of the input buffer in bytes.
519   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
520   * @retval HAL status
521   */
HAL_HASHEx_SHA256_Accumulate(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)522 HAL_StatusTypeDef HAL_HASHEx_SHA256_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
523 {
524     /* Process Locked */
525     __HAL_LOCK(hhash);
526 
527     /* Change the HASH state */
528     hhash->State = HAL_HASH_STATE_BUSY;
529 
530     /* Check if initialization phase has already been performed */
531     if (hhash->Phase == HAL_HASH_PHASE_READY) {
532         /* Select the SHA256 mode and reset the HASH processor core, so that the HASH will be ready to compute
533            the message digest of a new message */
534         HASH->CR |= HASH_ALGOSELECTION_SHA256 | HASH_CR_INIT;
535     }
536 
537     /* Set the phase */
538     hhash->Phase = HAL_HASH_PHASE_PROCESS;
539 
540     /* Configure the number of valid bits in last word of the message */
541     __HAL_HASH_SET_NBVALIDBITS(Size);
542 
543     /* Write input buffer in data register */
544     HASHEx_WriteData(pInBuffer, Size);
545 
546     /* Change the HASH state */
547     hhash->State = HAL_HASH_STATE_READY;
548 
549     /* Process Unlocked */
550     __HAL_UNLOCK(hhash);
551 
552     /* Return function status */
553     return HAL_OK;
554 }
555 
556 
557 /**
558   * @}
559   */
560 
561 /** @defgroup HASHEx_Group2 HMAC processing functions using polling mode
562  *  @brief   HMAC processing functions using polling mode .
563  *
564 @verbatim
565  ===============================================================================
566             ##### HMAC processing using polling mode functions #####
567  ===============================================================================
568     [..]  This section provides functions allowing to calculate in polling mode
569           the HMAC value using one of the following algorithms:
570       (+) SHA224
571       (+) SHA256
572 
573 @endverbatim
574   * @{
575   */
576 
577 /**
578   * @brief  Initializes the HASH peripheral in HMAC SHA224 mode
579   *         then processes pInBuffer. The digest is available in pOutBuffer.
580   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
581   *         the configuration information for HASH module
582   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
583   * @param  Size: Length of the input buffer in bytes.
584   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
585   * @param  pOutBuffer: Pointer to the computed digest. Its size must be 20 bytes.
586   * @param  Timeout: Timeout value
587   * @retval HAL status
588   */
HAL_HMACEx_SHA224_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)589 HAL_StatusTypeDef HAL_HMACEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
590 {
591     uint32_t tickstart = 0;
592 
593     /* Process Locked */
594     __HAL_LOCK(hhash);
595 
596     /* Change the HASH state */
597     hhash->State = HAL_HASH_STATE_BUSY;
598 
599     /* Check if initialization phase has already been performed */
600     if (hhash->Phase == HAL_HASH_PHASE_READY) {
601         /* Check if key size is greater than 64 bytes */
602         if (hhash->Init.KeySize > 64) {
603             /* Select the HMAC SHA224 mode */
604             HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
605         } else {
606             /* Select the HMAC SHA224 mode */
607             HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
608         }
609     }
610 
611     /* Set the phase */
612     hhash->Phase = HAL_HASH_PHASE_PROCESS;
613 
614     /************************** STEP 1 ******************************************/
615     /* Configure the number of valid bits in last word of the message */
616     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
617 
618     /* Write input buffer in data register */
619     HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize);
620 
621     /* Start the digest calculation */
622     __HAL_HASH_START_DIGEST();
623 
624     /* Get tick */
625     tickstart = HAL_GetTick();
626 
627     while ((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY) {
628         /* Check for the Timeout */
629         if (Timeout != HAL_MAX_DELAY) {
630             if ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) {
631                 /* Change state */
632                 hhash->State = HAL_HASH_STATE_TIMEOUT;
633 
634                 /* Process Unlocked */
635                 __HAL_UNLOCK(hhash);
636 
637                 return HAL_TIMEOUT;
638             }
639         }
640     }
641     /************************** STEP 2 ******************************************/
642     /* Configure the number of valid bits in last word of the message */
643     __HAL_HASH_SET_NBVALIDBITS(Size);
644 
645     /* Write input buffer in data register */
646     HASHEx_WriteData(pInBuffer, Size);
647 
648     /* Start the digest calculation */
649     __HAL_HASH_START_DIGEST();
650 
651     /* Get tick */
652     tickstart = HAL_GetTick();
653 
654     while ((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY) {
655         /* Check for the Timeout */
656         if (Timeout != HAL_MAX_DELAY) {
657             if ((HAL_GetTick() - tickstart ) > Timeout) {
658                 /* Change state */
659                 hhash->State = HAL_HASH_STATE_TIMEOUT;
660 
661                 /* Process Unlocked */
662                 __HAL_UNLOCK(hhash);
663 
664                 return HAL_TIMEOUT;
665             }
666         }
667     }
668     /************************** STEP 3 ******************************************/
669     /* Configure the number of valid bits in last word of the message */
670     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
671 
672     /* Write input buffer in data register */
673     HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize);
674 
675     /* Start the digest calculation */
676     __HAL_HASH_START_DIGEST();
677 
678     /* Get tick */
679     tickstart = HAL_GetTick();
680 
681     while ((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY) {
682         /* Check for the Timeout */
683         if (Timeout != HAL_MAX_DELAY) {
684             if ((HAL_GetTick() - tickstart ) > Timeout) {
685                 /* Change state */
686                 hhash->State = HAL_HASH_STATE_TIMEOUT;
687 
688                 /* Process Unlocked */
689                 __HAL_UNLOCK(hhash);
690 
691                 return HAL_TIMEOUT;
692             }
693         }
694     }
695     /* Read the message digest */
696     HASHEx_GetDigest(pOutBuffer, 28);
697 
698     /* Change the HASH state */
699     hhash->State = HAL_HASH_STATE_READY;
700 
701     /* Process Unlocked */
702     __HAL_UNLOCK(hhash);
703 
704     /* Return function status */
705     return HAL_OK;
706 }
707 
708 /**
709   * @brief  Initializes the HASH peripheral in HMAC SHA256 mode
710   *         then processes pInBuffer. The digest is available in pOutBuffer
711   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
712   *         the configuration information for HASH module
713   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
714   * @param  Size: Length of the input buffer in bytes.
715   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
716   * @param  pOutBuffer: Pointer to the computed digest. Its size must be 20 bytes.
717   * @param  Timeout: Timeout value
718   * @retval HAL status
719   */
HAL_HMACEx_SHA256_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)720 HAL_StatusTypeDef HAL_HMACEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
721 {
722     uint32_t tickstart = 0;
723 
724     /* Process Locked */
725     __HAL_LOCK(hhash);
726 
727     /* Change the HASH state */
728     hhash->State = HAL_HASH_STATE_BUSY;
729 
730     /* Check if initialization phase has already been performed */
731     if (hhash->Phase == HAL_HASH_PHASE_READY) {
732         /* Check if key size is greater than 64 bytes */
733         if (hhash->Init.KeySize > 64) {
734             /* Select the HMAC SHA256 mode */
735             HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY);
736         } else {
737             /* Select the HMAC SHA256 mode */
738             HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC);
739         }
740         /* Reset the HASH processor core, so that the HASH will be ready to compute
741            the message digest of a new message */
742         HASH->CR |= HASH_CR_INIT;
743     }
744 
745     /* Set the phase */
746     hhash->Phase = HAL_HASH_PHASE_PROCESS;
747 
748     /************************** STEP 1 ******************************************/
749     /* Configure the number of valid bits in last word of the message */
750     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
751 
752     /* Write input buffer in data register */
753     HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize);
754 
755     /* Start the digest calculation */
756     __HAL_HASH_START_DIGEST();
757 
758     /* Get tick */
759     tickstart = HAL_GetTick();
760 
761     while ((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY) {
762         /* Check for the Timeout */
763         if (Timeout != HAL_MAX_DELAY) {
764             if ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) {
765                 /* Change state */
766                 hhash->State = HAL_HASH_STATE_TIMEOUT;
767 
768                 /* Process Unlocked */
769                 __HAL_UNLOCK(hhash);
770 
771                 return HAL_TIMEOUT;
772             }
773         }
774     }
775     /************************** STEP 2 ******************************************/
776     /* Configure the number of valid bits in last word of the message */
777     __HAL_HASH_SET_NBVALIDBITS(Size);
778 
779     /* Write input buffer in data register */
780     HASHEx_WriteData(pInBuffer, Size);
781 
782     /* Start the digest calculation */
783     __HAL_HASH_START_DIGEST();
784 
785     /* Get tick */
786     tickstart = HAL_GetTick();
787 
788     while ((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY) {
789         /* Check for the Timeout */
790         if (Timeout != HAL_MAX_DELAY) {
791             if ((HAL_GetTick() - tickstart ) > Timeout) {
792                 /* Change state */
793                 hhash->State = HAL_HASH_STATE_TIMEOUT;
794 
795                 /* Process Unlocked */
796                 __HAL_UNLOCK(hhash);
797 
798                 return HAL_TIMEOUT;
799             }
800         }
801     }
802     /************************** STEP 3 ******************************************/
803     /* Configure the number of valid bits in last word of the message */
804     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
805 
806     /* Write input buffer in data register */
807     HASHEx_WriteData(hhash->Init.pKey, hhash->Init.KeySize);
808 
809     /* Start the digest calculation */
810     __HAL_HASH_START_DIGEST();
811 
812     /* Get tick */
813     tickstart = HAL_GetTick();
814 
815     while ((HASH->SR & HASH_FLAG_BUSY) == HASH_FLAG_BUSY) {
816         /* Check for the Timeout */
817         if (Timeout != HAL_MAX_DELAY) {
818             if ((HAL_GetTick() - tickstart ) > Timeout) {
819                 /* Change state */
820                 hhash->State = HAL_HASH_STATE_TIMEOUT;
821 
822                 /* Process Unlocked */
823                 __HAL_UNLOCK(hhash);
824 
825                 return HAL_TIMEOUT;
826             }
827         }
828     }
829     /* Read the message digest */
830     HASHEx_GetDigest(pOutBuffer, 32);
831 
832     /* Change the HASH state */
833     hhash->State = HAL_HASH_STATE_READY;
834 
835     /* Process Unlocked */
836     __HAL_UNLOCK(hhash);
837 
838     /* Return function status */
839     return HAL_OK;
840 }
841 
842 /**
843   * @}
844   */
845 
846 /** @defgroup HASHEx_Group3 HASH processing functions using interrupt mode
847  *  @brief   processing functions using interrupt mode.
848  *
849 @verbatim
850  ===============================================================================
851               ##### HASH processing using interrupt functions #####
852  ===============================================================================
853     [..]  This section provides functions allowing to calculate in interrupt mode
854           the hash value using one of the following algorithms:
855       (+) SHA224
856       (+) SHA256
857 
858 @endverbatim
859   * @{
860   */
861 
862 /**
863   * @brief  Initializes the HASH peripheral in SHA224 mode then processes pInBuffer.
864   *         The digest is available in pOutBuffer.
865   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
866   *         the configuration information for HASH module
867   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
868   * @param  Size: Length of the input buffer in bytes.
869   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
870   * @param  pOutBuffer: Pointer to the computed digest. Its size must be 20 bytes.
871   * @retval HAL status
872   */
HAL_HASHEx_SHA224_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)873 HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
874 {
875     uint32_t inputaddr;
876     uint32_t buffercounter;
877     uint32_t inputcounter;
878 
879     /* Process Locked */
880     __HAL_LOCK(hhash);
881 
882     if (hhash->State == HAL_HASH_STATE_READY) {
883         /* Change the HASH state */
884         hhash->State = HAL_HASH_STATE_BUSY;
885 
886         hhash->HashInCount = Size;
887         hhash->pHashInBuffPtr = pInBuffer;
888         hhash->pHashOutBuffPtr = pOutBuffer;
889 
890         /* Check if initialization phase has already been performed */
891         if (hhash->Phase == HAL_HASH_PHASE_READY) {
892             /* Select the SHA224 mode */
893             HASH->CR |= HASH_ALGOSELECTION_SHA224;
894             /* Reset the HASH processor core, so that the HASH will be ready to compute
895                the message digest of a new message */
896             HASH->CR |= HASH_CR_INIT;
897         }
898         /* Reset interrupt counter */
899         hhash->HashITCounter = 0;
900         /* Set the phase */
901         hhash->Phase = HAL_HASH_PHASE_PROCESS;
902 
903         /* Process Unlocked */
904         __HAL_UNLOCK(hhash);
905 
906         /* Enable Interrupts */
907         HASH->IMR = (HASH_IT_DINI | HASH_IT_DCI);
908 
909         /* Return function status */
910         return HAL_OK;
911     }
912     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS)) {
913         /* Read the message digest */
914         HASHEx_GetDigest(hhash->pHashOutBuffPtr, 28);
915         if (hhash->HashInCount == 0) {
916             /* Disable Interrupts */
917             HASH->IMR = 0;
918             /* Change the HASH state */
919             hhash->State = HAL_HASH_STATE_READY;
920             /* Call digest computation complete callback */
921             HAL_HASH_DgstCpltCallback(hhash);
922             /* Process Unlocked */
923             __HAL_UNLOCK(hhash);
924 
925             /* Return function status */
926             return HAL_OK;
927         }
928     }
929     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) {
930         if (hhash->HashInCount >= 68) {
931             inputaddr = (uint32_t)hhash->pHashInBuffPtr;
932             /* Write the Input block in the Data IN register */
933             for (buffercounter = 0; buffercounter < 64; buffercounter+=4) {
934                 HASH->DIN = *(uint32_t*)inputaddr;
935                 inputaddr+=4;
936             }
937             if (hhash->HashITCounter == 0) {
938                 HASH->DIN = *(uint32_t*)inputaddr;
939                 if (hhash->HashInCount >= 68) {
940                     /* Decrement buffer counter */
941                     hhash->HashInCount -= 68;
942                     hhash->pHashInBuffPtr+= 68;
943                 } else {
944                     hhash->HashInCount = 0;
945                     hhash->pHashInBuffPtr+= hhash->HashInCount;
946                 }
947                 /* Set Interrupt counter */
948                 hhash->HashITCounter = 1;
949             } else {
950                 /* Decrement buffer counter */
951                 hhash->HashInCount -= 64;
952                 hhash->pHashInBuffPtr+= 64;
953             }
954         } else {
955             /* Get the buffer address */
956             inputaddr = (uint32_t)hhash->pHashInBuffPtr;
957             /* Get the buffer counter */
958             inputcounter = hhash->HashInCount;
959             /* Disable Interrupts */
960             HASH->IMR &= ~(HASH_IT_DINI);
961             /* Configure the number of valid bits in last word of the message */
962             __HAL_HASH_SET_NBVALIDBITS(inputcounter);
963 
964             if ((inputcounter > 4) && (inputcounter%4)) {
965                 inputcounter = (inputcounter+4-inputcounter%4);
966             } else if ((inputcounter < 4) && (inputcounter != 0)) {
967                 inputcounter = 4;
968             }
969             /* Write the Input block in the Data IN register */
970             for (buffercounter = 0; buffercounter < inputcounter/4; buffercounter++) {
971                 HASH->DIN = *(uint32_t*)inputaddr;
972                 inputaddr+=4;
973             }
974             /* Start the digest calculation */
975             __HAL_HASH_START_DIGEST();
976             /* Reset buffer counter */
977             hhash->HashInCount = 0;
978             /* Call Input data transfer complete callback */
979             HAL_HASH_InCpltCallback(hhash);
980         }
981     }
982 
983     /* Process Unlocked */
984     __HAL_UNLOCK(hhash);
985 
986     /* Return function status */
987     return HAL_OK;
988 }
989 
990 
991 /**
992   * @brief  Initializes the HASH peripheral in SHA256 mode then processes pInBuffer.
993   *         The digest is available in pOutBuffer.
994   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
995   *         the configuration information for HASH module
996   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
997   * @param  Size: Length of the input buffer in bytes.
998   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
999   * @param  pOutBuffer: Pointer to the computed digest. Its size must be 20 bytes.
1000   * @retval HAL status
1001   */
HAL_HASHEx_SHA256_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1002 HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
1003 {
1004     uint32_t inputaddr;
1005     uint32_t buffercounter;
1006     uint32_t inputcounter;
1007 
1008     /* Process Locked */
1009     __HAL_LOCK(hhash);
1010 
1011     if (hhash->State == HAL_HASH_STATE_READY) {
1012         /* Change the HASH state */
1013         hhash->State = HAL_HASH_STATE_BUSY;
1014 
1015         hhash->HashInCount = Size;
1016         hhash->pHashInBuffPtr = pInBuffer;
1017         hhash->pHashOutBuffPtr = pOutBuffer;
1018 
1019         /* Check if initialization phase has already been performed */
1020         if (hhash->Phase == HAL_HASH_PHASE_READY) {
1021             /* Select the SHA256 mode */
1022             HASH->CR |= HASH_ALGOSELECTION_SHA256;
1023             /* Reset the HASH processor core, so that the HASH will be ready to compute
1024                the message digest of a new message */
1025             HASH->CR |= HASH_CR_INIT;
1026         }
1027 
1028         /* Reset interrupt counter */
1029         hhash->HashITCounter = 0;
1030 
1031         /* Set the phase */
1032         hhash->Phase = HAL_HASH_PHASE_PROCESS;
1033 
1034         /* Process Unlocked */
1035         __HAL_UNLOCK(hhash);
1036 
1037         /* Enable Interrupts */
1038         HASH->IMR = (HASH_IT_DINI | HASH_IT_DCI);
1039 
1040         /* Return function status */
1041         return HAL_OK;
1042     }
1043     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS)) {
1044         /* Read the message digest */
1045         HASHEx_GetDigest(hhash->pHashOutBuffPtr, 32);
1046         if (hhash->HashInCount == 0) {
1047             /* Disable Interrupts */
1048             HASH->IMR = 0;
1049             /* Change the HASH state */
1050             hhash->State = HAL_HASH_STATE_READY;
1051             /* Call digest computation complete callback */
1052             HAL_HASH_DgstCpltCallback(hhash);
1053 
1054             /* Process Unlocked */
1055             __HAL_UNLOCK(hhash);
1056 
1057             /* Return function status */
1058             return HAL_OK;
1059         }
1060     }
1061     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) {
1062         if (hhash->HashInCount >= 68) {
1063             inputaddr = (uint32_t)hhash->pHashInBuffPtr;
1064             /* Write the Input block in the Data IN register */
1065             for (buffercounter = 0; buffercounter < 64; buffercounter+=4) {
1066                 HASH->DIN = *(uint32_t*)inputaddr;
1067                 inputaddr+=4;
1068             }
1069             if (hhash->HashITCounter == 0) {
1070                 HASH->DIN = *(uint32_t*)inputaddr;
1071 
1072                 if (hhash->HashInCount >= 68) {
1073                     /* Decrement buffer counter */
1074                     hhash->HashInCount -= 68;
1075                     hhash->pHashInBuffPtr+= 68;
1076                 } else {
1077                     hhash->HashInCount = 0;
1078                     hhash->pHashInBuffPtr+= hhash->HashInCount;
1079                 }
1080                 /* Set Interrupt counter */
1081                 hhash->HashITCounter = 1;
1082             } else {
1083                 /* Decrement buffer counter */
1084                 hhash->HashInCount -= 64;
1085                 hhash->pHashInBuffPtr+= 64;
1086             }
1087         } else {
1088             /* Get the buffer address */
1089             inputaddr = (uint32_t)hhash->pHashInBuffPtr;
1090             /* Get the buffer counter */
1091             inputcounter = hhash->HashInCount;
1092             /* Disable Interrupts */
1093             HASH->IMR &= ~(HASH_IT_DINI);
1094             /* Configure the number of valid bits in last word of the message */
1095             __HAL_HASH_SET_NBVALIDBITS(inputcounter);
1096 
1097             if ((inputcounter > 4) && (inputcounter%4)) {
1098                 inputcounter = (inputcounter+4-inputcounter%4);
1099             } else if ((inputcounter < 4) && (inputcounter != 0)) {
1100                 inputcounter = 4;
1101             }
1102 
1103             /* Write the Input block in the Data IN register */
1104             for (buffercounter = 0; buffercounter < inputcounter/4; buffercounter++) {
1105                 HASH->DIN = *(uint32_t*)inputaddr;
1106                 inputaddr+=4;
1107             }
1108             /* Start the digest calculation */
1109             __HAL_HASH_START_DIGEST();
1110             /* Reset buffer counter */
1111             hhash->HashInCount = 0;
1112             /* Call Input data transfer complete callback */
1113             HAL_HASH_InCpltCallback(hhash);
1114         }
1115     }
1116 
1117     /* Process Unlocked */
1118     __HAL_UNLOCK(hhash);
1119 
1120     /* Return function status */
1121     return HAL_OK;
1122 }
1123 
1124 /**
1125   * @brief This function handles HASH interrupt request.
1126   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
1127   *         the configuration information for HASH module
1128   * @retval None
1129   */
HAL_HASHEx_IRQHandler(HASH_HandleTypeDef * hhash)1130 void HAL_HASHEx_IRQHandler(HASH_HandleTypeDef *hhash)
1131 {
1132     switch (HASH->CR & HASH_CR_ALGO) {
1133 
1134         case HASH_ALGOSELECTION_SHA224:
1135             HAL_HASHEx_SHA224_Start_IT(hhash, NULL, 0, NULL);
1136             break;
1137 
1138         case HASH_ALGOSELECTION_SHA256:
1139             HAL_HASHEx_SHA256_Start_IT(hhash, NULL, 0, NULL);
1140             break;
1141 
1142         default:
1143             break;
1144     }
1145 }
1146 
1147 /**
1148   * @}
1149   */
1150 
1151 /** @defgroup HASHEx_Group4 HASH processing functions using DMA mode
1152  *  @brief   processing functions using DMA mode.
1153  *
1154 @verbatim
1155  ===============================================================================
1156                 ##### HASH processing using DMA functions #####
1157  ===============================================================================
1158     [..]  This section provides functions allowing to calculate in DMA mode
1159           the hash value using one of the following algorithms:
1160       (+) SHA224
1161       (+) SHA256
1162 
1163 @endverbatim
1164   * @{
1165   */
1166 
1167 
1168 /**
1169   * @brief  Initializes the HASH peripheral in SHA224 mode then enables DMA to
1170             control data transfer. Use HAL_HASH_SHA224_Finish() to get the digest.
1171   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
1172   *         the configuration information for HASH module
1173   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
1174   * @param  Size: Length of the input buffer in bytes.
1175   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
1176   * @retval HAL status
1177   */
HAL_HASHEx_SHA224_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1178 HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1179 {
1180     uint32_t inputaddr  = (uint32_t)pInBuffer;
1181 
1182     /* Process Locked */
1183     __HAL_LOCK(hhash);
1184 
1185     /* Change the HASH state */
1186     hhash->State = HAL_HASH_STATE_BUSY;
1187 
1188     /* Check if initialization phase has already been performed */
1189     if (hhash->Phase == HAL_HASH_PHASE_READY) {
1190         /* Select the SHA224 mode and reset the HASH processor core, so that the HASH will be ready to compute
1191            the message digest of a new message */
1192         HASH->CR |= HASH_ALGOSELECTION_SHA224 | HASH_CR_INIT;
1193     }
1194 
1195     /* Configure the number of valid bits in last word of the message */
1196     __HAL_HASH_SET_NBVALIDBITS(Size);
1197 
1198     /* Set the phase */
1199     hhash->Phase = HAL_HASH_PHASE_PROCESS;
1200 
1201     /* Set the HASH DMA transfer complete callback */
1202     hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
1203     /* Set the DMA error callback */
1204     hhash->hdmain->XferErrorCallback = HASHEx_DMAError;
1205 
1206     /* Enable the DMA In DMA Stream */
1207     HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (Size%4 ? (Size+3)/4:Size/4));
1208 
1209     /* Enable DMA requests */
1210     HASH->CR |= (HASH_CR_DMAE);
1211 
1212     /* Process Unlocked */
1213     __HAL_UNLOCK(hhash);
1214 
1215     /* Return function status */
1216     return HAL_OK;
1217 }
1218 
1219 /**
1220   * @brief  Returns the computed digest in SHA224
1221   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
1222   *         the configuration information for HASH module
1223   * @param  pOutBuffer: Pointer to the computed digest. Its size must be 28 bytes.
1224   * @param  Timeout: Timeout value
1225   * @retval HAL status
1226   */
HAL_HASHEx_SHA224_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)1227 HAL_StatusTypeDef HAL_HASHEx_SHA224_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
1228 {
1229     uint32_t tickstart = 0;
1230 
1231     /* Process Locked */
1232     __HAL_LOCK(hhash);
1233 
1234     /* Change HASH peripheral state */
1235     hhash->State = HAL_HASH_STATE_BUSY;
1236 
1237     /* Get tick */
1238     tickstart = HAL_GetTick();
1239 
1240     while (HAL_IS_BIT_CLR(HASH->SR, HASH_FLAG_DCIS)) {
1241         /* Check for the Timeout */
1242         if (Timeout != HAL_MAX_DELAY) {
1243             if ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) {
1244                 /* Change state */
1245                 hhash->State = HAL_HASH_STATE_TIMEOUT;
1246 
1247                 /* Process Unlocked */
1248                 __HAL_UNLOCK(hhash);
1249 
1250                 return HAL_TIMEOUT;
1251             }
1252         }
1253     }
1254 
1255     /* Read the message digest */
1256     HASHEx_GetDigest(pOutBuffer, 28);
1257 
1258     /* Change HASH peripheral state */
1259     hhash->State = HAL_HASH_STATE_READY;
1260 
1261     /* Process Unlocked */
1262     __HAL_UNLOCK(hhash);
1263 
1264     /* Return function status */
1265     return HAL_OK;
1266 }
1267 
1268 /**
1269   * @brief  Initializes the HASH peripheral in SHA256 mode then enables DMA to
1270             control data transfer. Use HAL_HASH_SHA256_Finish() to get the digest.
1271   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
1272   *         the configuration information for HASH module
1273   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
1274   * @param  Size: Length of the input buffer in bytes.
1275   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
1276   * @retval HAL status
1277   */
HAL_HASHEx_SHA256_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1278 HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1279 {
1280     uint32_t inputaddr  = (uint32_t)pInBuffer;
1281 
1282     /* Process Locked */
1283     __HAL_LOCK(hhash);
1284 
1285     /* Change the HASH state */
1286     hhash->State = HAL_HASH_STATE_BUSY;
1287 
1288     /* Check if initialization phase has already been performed */
1289     if (hhash->Phase == HAL_HASH_PHASE_READY) {
1290         /* Select the SHA256 mode and reset the HASH processor core, so that the HASH will be ready to compute
1291            the message digest of a new message */
1292         HASH->CR |= HASH_ALGOSELECTION_SHA256 | HASH_CR_INIT;
1293     }
1294 
1295     /* Configure the number of valid bits in last word of the message */
1296     __HAL_HASH_SET_NBVALIDBITS(Size);
1297 
1298     /* Set the phase */
1299     hhash->Phase = HAL_HASH_PHASE_PROCESS;
1300 
1301     /* Set the HASH DMA transfer complete callback */
1302     hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
1303     /* Set the DMA error callback */
1304     hhash->hdmain->XferErrorCallback = HASHEx_DMAError;
1305 
1306     /* Enable the DMA In DMA Stream */
1307     HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (Size%4 ? (Size+3)/4:Size/4));
1308 
1309     /* Enable DMA requests */
1310     HASH->CR |= (HASH_CR_DMAE);
1311 
1312     /* Process UnLock */
1313     __HAL_UNLOCK(hhash);
1314 
1315     /* Return function status */
1316     return HAL_OK;
1317 }
1318 
1319 /**
1320   * @brief  Returns the computed digest in SHA256.
1321   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
1322   *         the configuration information for HASH module
1323   * @param  pOutBuffer: Pointer to the computed digest. Its size must be 32 bytes.
1324   * @param  Timeout: Timeout value
1325   * @retval HAL status
1326   */
HAL_HASHEx_SHA256_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)1327 HAL_StatusTypeDef HAL_HASHEx_SHA256_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
1328 {
1329     uint32_t tickstart = 0;
1330 
1331     /* Process Locked */
1332     __HAL_LOCK(hhash);
1333 
1334     /* Change HASH peripheral state */
1335     hhash->State = HAL_HASH_STATE_BUSY;
1336 
1337     /* Get tick */
1338     tickstart = HAL_GetTick();
1339 
1340     while (HAL_IS_BIT_CLR(HASH->SR, HASH_FLAG_DCIS)) {
1341         /* Check for the Timeout */
1342         if (Timeout != HAL_MAX_DELAY) {
1343             if ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) {
1344                 /* Change state */
1345                 hhash->State = HAL_HASH_STATE_TIMEOUT;
1346 
1347                 /* Process Unlocked */
1348                 __HAL_UNLOCK(hhash);
1349 
1350                 return HAL_TIMEOUT;
1351             }
1352         }
1353     }
1354 
1355     /* Read the message digest */
1356     HASHEx_GetDigest(pOutBuffer, 32);
1357 
1358     /* Change HASH peripheral state */
1359     hhash->State = HAL_HASH_STATE_READY;
1360 
1361     /* Process Unlocked */
1362     __HAL_UNLOCK(hhash);
1363 
1364     /* Return function status */
1365     return HAL_OK;
1366 }
1367 
1368 
1369 /**
1370   * @}
1371   */
1372 /** @defgroup HASHEx_Group5 HMAC processing functions using DMA mode
1373  *  @brief   HMAC processing functions using DMA mode .
1374  *
1375 @verbatim
1376  ===============================================================================
1377                 ##### HMAC processing using DMA functions #####
1378  ===============================================================================
1379     [..]  This section provides functions allowing to calculate in DMA mode
1380           the HMAC value using one of the following algorithms:
1381       (+) SHA224
1382       (+) SHA256
1383 
1384 @endverbatim
1385   * @{
1386   */
1387 
1388 /**
1389   * @brief  Initializes the HASH peripheral in HMAC SHA224 mode
1390   *         then enables DMA to control data transfer.
1391   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
1392   *         the configuration information for HASH module
1393   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
1394   * @param  Size: Length of the input buffer in bytes.
1395   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
1396   * @retval HAL status
1397   */
HAL_HMACEx_SHA224_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1398 HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1399 {
1400     uint32_t inputaddr;
1401 
1402     /* Process Locked */
1403     __HAL_LOCK(hhash);
1404 
1405     /* Change the HASH state */
1406     hhash->State = HAL_HASH_STATE_BUSY;
1407 
1408     /* Save buffer pointer and size in handle */
1409     hhash->pHashInBuffPtr = pInBuffer;
1410     hhash->HashBuffSize = Size;
1411     hhash->HashInCount = 0;
1412 
1413     /* Check if initialization phase has already been performed */
1414     if (hhash->Phase == HAL_HASH_PHASE_READY) {
1415         /* Check if key size is greater than 64 bytes */
1416         if (hhash->Init.KeySize > 64) {
1417             /* Select the HMAC SHA224 mode */
1418             HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
1419         } else {
1420             /* Select the HMAC SHA224 mode */
1421             HASH->CR |= (HASH_ALGOSELECTION_SHA224 | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
1422         }
1423     }
1424 
1425     /* Set the phase */
1426     hhash->Phase = HAL_HASH_PHASE_PROCESS;
1427 
1428     /* Configure the number of valid bits in last word of the message */
1429     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
1430 
1431     /* Get the key address */
1432     inputaddr = (uint32_t)(hhash->Init.pKey);
1433 
1434     /* Set the HASH DMA transfer complete callback */
1435     hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
1436     /* Set the DMA error callback */
1437     hhash->hdmain->XferErrorCallback = HASHEx_DMAError;
1438 
1439     /* Enable the DMA In DMA Stream */
1440     HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (hhash->Init.KeySize%4 ? (hhash->Init.KeySize+3)/4:hhash->Init.KeySize/4));
1441     /* Enable DMA requests */
1442     HASH->CR |= (HASH_CR_DMAE);
1443 
1444     /* Process Unlocked */
1445     __HAL_UNLOCK(hhash);
1446 
1447     /* Return function status */
1448     return HAL_OK;
1449 }
1450 
1451 /**
1452   * @brief  Initializes the HASH peripheral in HMAC SHA256 mode
1453   *         then enables DMA to control data transfer.
1454   * @param  hhash: pointer to a HASH_HandleTypeDef structure that contains
1455   *         the configuration information for HASH module
1456   * @param  pInBuffer: Pointer to the input buffer (buffer to be hashed).
1457   * @param  Size: Length of the input buffer in bytes.
1458   *          If the Size is not multiple of 64 bytes, the padding is managed by hardware.
1459   * @retval HAL status
1460   */
HAL_HMACEx_SHA256_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1461 HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1462 {
1463     uint32_t inputaddr;
1464 
1465     /* Process Locked */
1466     __HAL_LOCK(hhash);
1467 
1468     /* Change the HASH state */
1469     hhash->State = HAL_HASH_STATE_BUSY;
1470 
1471     /* Save buffer pointer and size in handle */
1472     hhash->pHashInBuffPtr = pInBuffer;
1473     hhash->HashBuffSize = Size;
1474     hhash->HashInCount = 0;
1475 
1476     /* Check if initialization phase has already been performed */
1477     if (hhash->Phase == HAL_HASH_PHASE_READY) {
1478         /* Check if key size is greater than 64 bytes */
1479         if (hhash->Init.KeySize > 64) {
1480             /* Select the HMAC SHA256 mode */
1481             HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY);
1482         } else {
1483             /* Select the HMAC SHA256 mode */
1484             HASH->CR |= (HASH_ALGOSELECTION_SHA256 | HASH_ALGOMODE_HMAC);
1485         }
1486         /* Reset the HASH processor core, so that the HASH will be ready to compute
1487            the message digest of a new message */
1488         HASH->CR |= HASH_CR_INIT;
1489     }
1490 
1491     /* Set the phase */
1492     hhash->Phase = HAL_HASH_PHASE_PROCESS;
1493 
1494     /* Configure the number of valid bits in last word of the message */
1495     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
1496 
1497     /* Get the key address */
1498     inputaddr = (uint32_t)(hhash->Init.pKey);
1499 
1500     /* Set the HASH DMA transfer complete callback */
1501     hhash->hdmain->XferCpltCallback = HASHEx_DMAXferCplt;
1502     /* Set the DMA error callback */
1503     hhash->hdmain->XferErrorCallback = HASHEx_DMAError;
1504 
1505     /* Enable the DMA In DMA Stream */
1506     HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (hhash->Init.KeySize%4 ? (hhash->Init.KeySize+3)/4:hhash->Init.KeySize/4));
1507     /* Enable DMA requests */
1508     HASH->CR |= (HASH_CR_DMAE);
1509 
1510     /* Process Unlocked */
1511     __HAL_UNLOCK(hhash);
1512 
1513     /* Return function status */
1514     return HAL_OK;
1515 }
1516 
1517 /**
1518   * @}
1519   */
1520 
1521 /**
1522   * @}
1523   */
1524 #endif /* HAL_HASH_MODULE_ENABLED */
1525 
1526 /**
1527   * @}
1528   */
1529 #endif /* STM32F756xx */
1530 
1531 /**
1532   * @}
1533   */
1534 
1535 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1536