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