1 //*****************************************************************************
2 //
3 // shamd5.c - Driver for the SHA/MD5 module.
4 //
5 // Copyright (c) 2012-2020 Texas Instruments Incorporated. All rights reserved.
6 // Software License Agreement
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 // Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright
16 // notice, this list of conditions and the following disclaimer in the
17 // documentation and/or other materials provided with the
18 // distribution.
19 //
20 // Neither the name of Texas Instruments Incorporated nor the names of
21 // its contributors may be used to endorse or promote products derived
22 // from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 //
36 // This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library.
37 //
38 //*****************************************************************************
39
40 #include <stdbool.h>
41 #include <stdint.h>
42 #include "inc/hw_ints.h"
43 #include "inc/hw_memmap.h"
44 #include "inc/hw_nvic.h"
45 #include "inc/hw_shamd5.h"
46 #include "inc/hw_types.h"
47 #include "driverlib/debug.h"
48 #include "driverlib/interrupt.h"
49 #include "driverlib/shamd5.h"
50
51 //*****************************************************************************
52 //
53 //! \addtogroup shamd5_api
54 //! @{
55 //
56 //*****************************************************************************
57
58 //*****************************************************************************
59 //
60 //! Resets the SHA/MD5 module.
61 //!
62 //! \param ui32Base is the base address of the SHA/MD5 module.
63 //!
64 //! This function performs a soft-reset of the SHA/MD5 module using the
65 //! SYSCONFIG register.
66 //!
67 //! \return None.
68 //
69 //*****************************************************************************
70 void
SHAMD5Reset(uint32_t ui32Base)71 SHAMD5Reset(uint32_t ui32Base)
72 {
73 //
74 // Check the arguments.
75 //
76 ASSERT(ui32Base == SHAMD5_BASE);
77
78 //
79 // Set the soft-reset bit.
80 //
81 HWREG(ui32Base + SHAMD5_O_SYSCONFIG) |= SHAMD5_SYSCONFIG_SOFTRESET;
82
83 //
84 // Wait for the reset to complete.
85 //
86 while((HWREG(ui32Base + SHAMD5_O_SYSSTATUS) &
87 SHAMD5_SYSSTATUS_RESETDONE) == 0)
88 {
89 }
90
91 //
92 // Force idle mode.
93 //
94 HWREG(ui32Base + SHAMD5_O_SYSCONFIG) =
95 ((HWREG(ui32Base + SHAMD5_O_SYSCONFIG) & ~SHAMD5_SYSCONFIG_SIDLE_M) |
96 SHAMD5_SYSCONFIG_SIDLE_FORCE);
97 }
98
99 //*****************************************************************************
100 //
101 //! Enables the uDMA requests in the SHA/MD5 module.
102 //!
103 //! \param ui32Base is the base address of the SHA/MD5 module.
104 //!
105 //! This function configures the DMA options of the SHA/MD5 module.
106 //!
107 //! \return None
108 //
109 //*****************************************************************************
110 void
SHAMD5DMAEnable(uint32_t ui32Base)111 SHAMD5DMAEnable(uint32_t ui32Base)
112 {
113 //
114 // Check the arguments.
115 //
116 ASSERT(ui32Base == SHAMD5_BASE);
117
118 //
119 // Write the new configuration into the register.
120 //
121 HWREG(ui32Base + SHAMD5_O_SYSCONFIG) |=
122 SHAMD5_SYSCONFIG_SADVANCED | SHAMD5_SYSCONFIG_DMA_EN;
123 }
124
125 //*****************************************************************************
126 //
127 //! Disables the uDMA requests in the SHA/MD5 module.
128 //!
129 //! \param ui32Base is the base address of the SHA/MD5 module.
130 //!
131 //! This function configures the DMA options of the SHA/MD5 module.
132 //!
133 //! \return None
134 //
135 //*****************************************************************************
136 void
SHAMD5DMADisable(uint32_t ui32Base)137 SHAMD5DMADisable(uint32_t ui32Base)
138 {
139 //
140 // Check the arguments.
141 //
142 ASSERT(ui32Base == SHAMD5_BASE);
143
144 //
145 // Write the new configuration into the register.
146 //
147 HWREG(ui32Base + SHAMD5_O_SYSCONFIG) &=
148 ~(SHAMD5_SYSCONFIG_SADVANCED | SHAMD5_SYSCONFIG_DMA_EN);
149 }
150
151 //*****************************************************************************
152 //
153 //! Get the interrupt status of the SHA/MD5 module.
154 //!
155 //! \param ui32Base is the base address of the SHA/MD5 module.
156 //! \param bMasked is \b false if the raw interrupt status is required and
157 //! \b true if the masked interrupt status is required.
158 //!
159 //! This function returns the current value of the IRQSTATUS register. The
160 //! value will be a logical OR of the following:
161 //!
162 //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready.
163 //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after
164 //! a context switch.
165 //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data.
166 //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready.
167 //!
168 //! \return Interrupt status
169 //
170 //*****************************************************************************
171 uint32_t
SHAMD5IntStatus(uint32_t ui32Base,bool bMasked)172 SHAMD5IntStatus(uint32_t ui32Base, bool bMasked)
173 {
174 uint32_t ui32Status, ui32Enable, ui32Temp;
175
176 //
177 // Check the arguments.
178 //
179 ASSERT(ui32Base == SHAMD5_BASE);
180
181 //
182 // Return the value of the IRQSTATUS register.
183 //
184 ui32Status = HWREG(ui32Base + SHAMD5_O_IRQSTATUS);
185 if(bMasked)
186 {
187 ui32Enable = HWREG(ui32Base + SHAMD5_O_IRQENABLE);
188 ui32Temp = HWREG(ui32Base + SHAMD5_O_DMAMIS);
189 return((ui32Status & ui32Enable) |
190 ((ui32Temp & 0x00000001) << 19) |
191 ((ui32Temp & 0x00000002) << 16) |
192 ((ui32Temp & 0x00000004) << 14));
193 }
194 else
195 {
196 ui32Temp = HWREG(ui32Base + SHAMD5_O_DMARIS);
197 return(ui32Status |
198 ((ui32Temp & 0x00000001) << 19) |
199 ((ui32Temp & 0x00000002) << 16) |
200 ((ui32Temp & 0x00000004) << 14));
201 }
202 }
203
204 //*****************************************************************************
205 //
206 //! Enable interrupt sources in the SHA/MD5 module.
207 //!
208 //! \param ui32Base is the base address of the SHA/MD5 module.
209 //! \param ui32IntFlags contains desired interrupts to enable.
210 //!
211 //! This function enables interrupt sources in the SHA/MD5 module.
212 //! ui32IntFlags must be a logical OR of one or more of the following
213 //! values:
214 //!
215 //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready.
216 //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after
217 //! a context switch.
218 //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data.
219 //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready.
220 //!
221 //! \return None.
222 //
223 //*****************************************************************************
224 void
SHAMD5IntEnable(uint32_t ui32Base,uint32_t ui32IntFlags)225 SHAMD5IntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
226 {
227 //
228 // Check the arguments.
229 //
230 ASSERT(ui32Base == SHAMD5_BASE);
231 ASSERT((ui32IntFlags == SHAMD5_INT_CONTEXT_READY) ||
232 (ui32IntFlags == SHAMD5_INT_PARTHASH_READY) ||
233 (ui32IntFlags == SHAMD5_INT_INPUT_READY) ||
234 (ui32IntFlags == SHAMD5_INT_OUTPUT_READY));
235
236 //
237 // Enable the interrupt sources.
238 //
239 HWREG(ui32Base + SHAMD5_O_DMAIM) |= (((ui32IntFlags & 0x00010000) >> 14) |
240 ((ui32IntFlags & 0x00020000) >> 16) |
241 ((ui32IntFlags & 0x00040000) >> 19));
242 HWREG(ui32Base + SHAMD5_O_IRQENABLE) |= ui32IntFlags & 0x0000ffff;
243
244 //
245 // Enable all interrupts.
246 //
247 HWREG(ui32Base + SHAMD5_O_SYSCONFIG) |= SHAMD5_SYSCONFIG_IT_EN;
248 }
249
250 //*****************************************************************************
251 //
252 //! Disable interrupt sources in the SHA/MD5 module.
253 //!
254 //! \param ui32Base is the base address of the SHA/MD5 module.
255 //! \param ui32IntFlags contains desired interrupts to disable.
256 //!
257 //! \e ui32IntFlags must be a logical OR of one or more of the following
258 //! values:
259 //!
260 //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready.
261 //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after
262 //! a context switch.
263 //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data.
264 //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready.
265 //!
266 //! \return None.
267 //
268 //*****************************************************************************
269 void
SHAMD5IntDisable(uint32_t ui32Base,uint32_t ui32IntFlags)270 SHAMD5IntDisable(uint32_t ui32Base, uint32_t ui32IntFlags)
271 {
272 //
273 // Check the arguments.
274 //
275 ASSERT(ui32Base == SHAMD5_BASE);
276 ASSERT((ui32IntFlags == SHAMD5_INT_CONTEXT_READY) ||
277 (ui32IntFlags == SHAMD5_INT_PARTHASH_READY) ||
278 (ui32IntFlags == SHAMD5_INT_INPUT_READY) ||
279 (ui32IntFlags == SHAMD5_INT_OUTPUT_READY));
280
281 //
282 // Clear the corresponding flags disabling the interrupt sources.
283 //
284 HWREG(ui32Base + SHAMD5_O_DMAIM) &= ~(((ui32IntFlags & 0x00010000) >> 14) |
285 ((ui32IntFlags & 0x00020000) >> 16) |
286 ((ui32IntFlags & 0x00040000) >> 19));
287 HWREG(ui32Base + SHAMD5_O_IRQENABLE) &= ~(ui32IntFlags & 0x0000ffff);
288
289 //
290 // If there are no interrupts enabled, then disable all interrupts.
291 //
292 if(HWREG(ui32Base + SHAMD5_O_IRQENABLE) == 0x0)
293 {
294 HWREG(ui32Base + SHAMD5_O_SYSCONFIG) &= ~SHAMD5_SYSCONFIG_IT_EN;
295 }
296 }
297
298 //*****************************************************************************
299 //
300 //! Clears interrupt sources in the SHA/MD5 module.
301 //!
302 //! \param ui32Base is the base address of the SHA/MD5 module.
303 //! \param ui32IntFlags contains desired interrupts to disable.
304 //!
305 //! \e ui32IntFlags must be a logical OR of one or more of the following
306 //! values:
307 //!
308 //! - \b SHAMD5_INT_CONTEXT_READY - Context input registers are ready.
309 //! - \b SHAMD5_INT_PARTHASH_READY - Context output registers are ready after
310 //! a context switch.
311 //! - \b SHAMD5_INT_INPUT_READY - Data FIFO is ready to receive data.
312 //! - \b SHAMD5_INT_OUTPUT_READY - Context output registers are ready.
313 //!
314 //! \return None.
315 //
316 //*****************************************************************************
317 void
SHAMD5IntClear(uint32_t ui32Base,uint32_t ui32IntFlags)318 SHAMD5IntClear(uint32_t ui32Base, uint32_t ui32IntFlags)
319 {
320 //
321 // Check the arguments.
322 //
323 ASSERT(ui32Base == SHAMD5_BASE);
324 ASSERT((ui32IntFlags == SHAMD5_INT_CONTEXT_READY) ||
325 (ui32IntFlags == SHAMD5_INT_PARTHASH_READY) ||
326 (ui32IntFlags == SHAMD5_INT_INPUT_READY) ||
327 (ui32IntFlags == SHAMD5_INT_OUTPUT_READY));
328
329 //
330 // Clear the corresponding flags disabling the interrupt sources.
331 //
332 HWREG(ui32Base + SHAMD5_O_DMAIC) = (((ui32IntFlags & 0x00010000) >> 14) |
333 ((ui32IntFlags & 0x00020000) >> 16) |
334 ((ui32IntFlags & 0x00040000) >> 19));
335 }
336
337 //*****************************************************************************
338 //
339 //! Registers an interrupt handler for the SHA/MD5 module.
340 //!
341 //! \param ui32Base is the base address of the SHA/MD5 module.
342 //! \param pfnHandler is a pointer to the function to be called when the
343 //! enabled SHA/MD5 interrupts occur.
344 //!
345 //! This function registers the interrupt handler in the interrupt vector
346 //! table, and enables SHA/MD5 interrupts on the interrupt controller;
347 //! specific SHA/MD5 interrupt sources must be enabled using
348 //! SHAMD5IntEnable(). The interrupt handler being registered must clear
349 //! the source of the interrupt using SHAMD5IntClear().
350 //!
351 //! If the application is using a static interrupt vector table stored in
352 //! flash, then it is not necessary to register the interrupt handler this way.
353 //! Instead, IntEnable() should be used to enable SHA/MD5 interrupts on the
354 //! interrupt controller.
355 //!
356 //! \sa IntRegister() for important information about registering interrupt
357 //! handlers.
358 //!
359 //! \return None.
360 //
361 //*****************************************************************************
362 void
SHAMD5IntRegister(uint32_t ui32Base,void (* pfnHandler)(void))363 SHAMD5IntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
364 {
365 //
366 // Check the arguments.
367 //
368 ASSERT(ui32Base == SHAMD5_BASE);
369
370 //
371 // Register the interrupt handler.
372 //
373 IntRegister(INT_SHA0_TM4C129, pfnHandler);
374
375 //
376 // Enable the interrupt
377 //
378 IntEnable(INT_SHA0_TM4C129);
379 }
380
381 //*****************************************************************************
382 //
383 //! Unregisters an interrupt handler for the SHA/MD5 module.
384 //!
385 //! \param ui32Base is the base address of the SHA/MD5 module.
386 //!
387 //! This function unregisters the previously registered interrupt handler and
388 //! disables the interrupt in the interrupt controller.
389 //!
390 //! \sa IntRegister() for important information about registering interrupt
391 //! handlers.
392 //!
393 //! \return None.
394 //
395 //*****************************************************************************
396 void
SHAMD5IntUnregister(uint32_t ui32Base)397 SHAMD5IntUnregister(uint32_t ui32Base)
398 {
399 //
400 // Check the arguments.
401 //
402 ASSERT(ui32Base == SHAMD5_BASE);
403
404 //
405 // Disable the interrupt.
406 //
407 IntDisable(INT_SHA0_TM4C129);
408
409 //
410 // Unregister the interrupt handler.
411 //
412 IntUnregister(INT_SHA0_TM4C129);
413 }
414
415 //*****************************************************************************
416 //
417 //! Write the hash length to the SHA/MD5 module.
418 //!
419 //! \param ui32Base is the base address of the SHA/MD5 module.
420 //! \param ui32Length is the hash length in bytes.
421 //!
422 //! This function writes the length of the hash data of the current operation
423 //! to the SHA/MD5 module. The value must be a multiple of 64 if the close
424 //! hash is not set in the mode register.
425 //!
426 //! \note When this register is written, hash processing is triggered.
427 //!
428 //! \return None.
429 //
430 //*****************************************************************************
431 void
SHAMD5HashLengthSet(uint32_t ui32Base,uint32_t ui32Length)432 SHAMD5HashLengthSet(uint32_t ui32Base, uint32_t ui32Length)
433 {
434 //
435 // Check the arguments.
436 //
437 ASSERT(ui32Base == SHAMD5_BASE);
438
439 //
440 // Set the LENGTH register and start processing.
441 //
442 HWREG(ui32Base + SHAMD5_O_LENGTH) = ui32Length;
443 }
444
445 //*****************************************************************************
446 //
447 //! Writes the mode in the SHA/MD5 module.
448 //!
449 //! \param ui32Base is the base address of the SHA/MD5 module.
450 //! \param ui32Mode is the mode of the SHA/MD5 module.
451 //!
452 //! This function writes the mode register configuring the SHA/MD5 module.
453 //!
454 //! The ui32Mode parameter is a bit-wise OR of values:
455 //!
456 //! - \b SHAMD5_ALGO_MD5 - Regular hash with MD5
457 //! - \b SHAMD5_ALGO_SHA1 - Regular hash with SHA-1
458 //! - \b SHAMD5_ALGO_SHA224 - Regular hash with SHA-224
459 //! - \b SHAMD5_ALGO_SHA256 - Regular hash with SHA-256
460 //! - \b SHAMD5_ALGO_HMAC_MD5 - HMAC with MD5
461 //! - \b SHAMD5_ALGO_HMAC_SHA1 - HMAC with SHA-1
462 //! - \b SHAMD5_ALGO_HMAC_SHA224 - HMAC with SHA-224
463 //! - \b SHAMD5_ALGO_HMAC_SHA256 - HMAC with SHA-256
464 //!
465 //! \return None
466 //
467 //*****************************************************************************
468 void
SHAMD5ConfigSet(uint32_t ui32Base,uint32_t ui32Mode)469 SHAMD5ConfigSet(uint32_t ui32Base, uint32_t ui32Mode)
470 {
471 //
472 // Check the arguments.
473 //
474 ASSERT(ui32Base == SHAMD5_BASE);
475 ASSERT((ui32Mode == SHAMD5_ALGO_MD5) ||
476 (ui32Mode == SHAMD5_ALGO_SHA1) ||
477 (ui32Mode == SHAMD5_ALGO_SHA224) ||
478 (ui32Mode == SHAMD5_ALGO_SHA256) ||
479 (ui32Mode == SHAMD5_ALGO_HMAC_MD5) ||
480 (ui32Mode == SHAMD5_ALGO_HMAC_SHA1) ||
481 (ui32Mode == SHAMD5_ALGO_HMAC_SHA224) ||
482 (ui32Mode == SHAMD5_ALGO_HMAC_SHA256));
483
484 //
485 // Write the value in the MODE register.
486 //
487 HWREG(ui32Base + SHAMD5_O_MODE) = ui32Mode;
488 }
489
490 //*****************************************************************************
491 //
492 //! Perform a non-blocking write of 16 words of data to the SHA/MD5 module.
493 //!
494 //! \param ui32Base is the base address of the SHA/MD5 module.
495 //! \param pui32Src is the pointer to the 16-word array of data that will be
496 //! written.
497 //!
498 //! This function writes 16 words of data into the data register regardless
499 //! of whether or not the module is ready to accept the data.
500 //!
501 //! \return This function returns true if the write completed successfully.
502 //! It returns false if the module was not ready.
503 //
504 //*****************************************************************************
505 bool
SHAMD5DataWriteNonBlocking(uint32_t ui32Base,uint32_t * pui32Src)506 SHAMD5DataWriteNonBlocking(uint32_t ui32Base, uint32_t *pui32Src)
507 {
508 uint32_t ui32Counter;
509
510 //
511 // Check the arguments.
512 //
513 ASSERT(ui32Base == SHAMD5_BASE);
514
515 //
516 // Check that the SHA/MD5 module is ready for data. If not, return false.
517 //
518 if((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_INPUT_READY) == 0)
519 {
520 return(false);
521 }
522
523 //
524 // Write the 16 words of data.
525 //
526 for(ui32Counter = 0; ui32Counter < 64; ui32Counter += 4)
527 {
528 HWREG(ui32Base + SHAMD5_O_DATA_0_IN + ui32Counter) = *pui32Src++;
529 }
530
531 //
532 // Return true as a sign of successfully completing the function.
533 //
534 return(true);
535 }
536
537 //*****************************************************************************
538 //
539 //! Perform a blocking write of 16 words of data to the SHA/MD5 module.
540 //!
541 //! \param ui32Base is the base address of the SHA/MD5 module.
542 //! \param pui32Src is the pointer to the 16-word array of data that will be
543 //! written.
544 //!
545 //! This function does not return until the module is ready to accept data and
546 //! the data has been written.
547 //!
548 //! \return None.
549 //
550 //*****************************************************************************
551 void
SHAMD5DataWrite(uint32_t ui32Base,uint32_t * pui32Src)552 SHAMD5DataWrite(uint32_t ui32Base, uint32_t *pui32Src)
553 {
554 uint32_t ui32Counter;
555
556 //
557 // Check the arguments.
558 //
559 ASSERT(ui32Base == SHAMD5_BASE);
560
561 //
562 // Wait for the module to be ready to accept data.
563 //
564 while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_INPUT_READY) == 0)
565 {
566 }
567
568 //
569 // Write the 16 words of data.
570 //
571 for(ui32Counter = 0; ui32Counter < 64; ui32Counter += 4)
572 {
573 HWREG(ui32Base + SHAMD5_O_DATA_0_IN + ui32Counter) = *pui32Src++;
574 }
575 }
576
577 //*****************************************************************************
578 //
579 //! Reads the result of a hashing operation.
580 //!
581 //! \param ui32Base is the base address of the SHA/MD5 module.
582 //! \param pui32Dest is the pointer to the 16-word array of data that will be
583 //! written.
584 //!
585 //! This function does not return until the module is ready to accept data and
586 //! the data has been written.
587 //!
588 //! \return None.
589 //
590 //*****************************************************************************
591 void
SHAMD5ResultRead(uint32_t ui32Base,uint32_t * pui32Dest)592 SHAMD5ResultRead(uint32_t ui32Base, uint32_t *pui32Dest)
593 {
594 uint32_t ui32Idx, ui32Count;
595
596 //
597 // Check the arguments.
598 //
599 ASSERT(ui32Base == SHAMD5_BASE);
600
601 //
602 // Determine the number of bytes in the result, based on the hash type.
603 //
604 switch(HWREG(ui32Base + SHAMD5_O_MODE) & SHAMD5_MODE_ALGO_M)
605 {
606 //
607 // The MD5 hash is being used.
608 //
609 case SHAMD5_MODE_ALGO_MD5:
610 {
611 //
612 // There are 16 bytes in the MD5 hash.
613 //
614 ui32Count = 16;
615
616 //
617 // Done.
618 //
619 break;
620 }
621
622 //
623 // The SHA-1 hash is being used.
624 //
625 case SHAMD5_MODE_ALGO_SHA1:
626 {
627 //
628 // There are 20 bytes in the SHA-1 hash.
629 //
630 ui32Count = 20;
631
632 //
633 // Done.
634 //
635 break;
636 }
637
638 //
639 // The SHA-224 hash is being used.
640 //
641 case SHAMD5_MODE_ALGO_SHA224:
642 {
643 //
644 // There are 28 bytes in the SHA-224 hash.
645 //
646 ui32Count = 28;
647
648 //
649 // Done.
650 //
651 break;
652 }
653
654 //
655 // The SHA-256 hash is being used.
656 //
657 case SHAMD5_MODE_ALGO_SHA256:
658 {
659 //
660 // There are 32 bytes in the SHA-256 hash.
661 //
662 ui32Count = 32;
663
664 //
665 // Done.
666 //
667 break;
668 }
669
670 //
671 // The hash type is not recognized.
672 //
673 default:
674 {
675 //
676 // Return without reading a result since the hardware appears to be
677 // misconfigured.
678 //
679 return;
680 }
681 }
682
683 //
684 // Read the hash result.
685 //
686 for(ui32Idx = 0; ui32Idx < ui32Count; ui32Idx += 4)
687 {
688 *pui32Dest++ = HWREG(ui32Base + SHAMD5_O_IDIGEST_A + ui32Idx);
689 }
690 }
691
692 //*****************************************************************************
693 //
694 //! Writes multiple words of data into the SHA/MD5 data registers.
695 //!
696 //! \param ui32Base is the base address of the SHA/MD5 module.
697 //! \param pui32DataSrc is a pointer to an array of data to be written.
698 //! \param ui32DataLength is the length of the data to be written in bytes.
699 //!
700 //! This function writes a variable number of words into the SHA/MD5 data
701 //! registers. The function waits for each block of data to be processed
702 //! before another is written. The \e ui32DataLength parameter must be a
703 //! multiple of 4 to fall on a word boundry.
704 //!
705 //! \note This function is used by SHAMD5DataProcess() and SHAMD5HMACProcess()
706 //! to process data.
707 //!
708 //! \return None.
709 //
710 //*****************************************************************************
711 static void
_SHAMD5DataWriteMultiple(uint32_t ui32Base,uint32_t * pui32DataSrc,uint32_t ui32DataLength)712 _SHAMD5DataWriteMultiple(uint32_t ui32Base, uint32_t *pui32DataSrc,
713 uint32_t ui32DataLength)
714 {
715 uint32_t ui32Idx, ui32Count;
716
717 //
718 // Check the arguments.
719 //
720 ASSERT(ui32Base == SHAMD5_BASE);
721
722 //
723 // Calculate the number of blocks of data.
724 //
725 ui32Count = ui32DataLength / 64;
726
727 //
728 // Loop through all the blocks and write them into the data registers
729 // making sure to block additional operations until we can write the
730 // next 16 words.
731 //
732 for(ui32Idx = 0; ui32Idx < ui32Count; ui32Idx++)
733 {
734 //
735 // Write the block of data.
736 //
737 SHAMD5DataWrite(ui32Base, pui32DataSrc);
738
739 //
740 // Increment the pointer to next block of data.
741 //
742 pui32DataSrc += 16;
743 }
744
745 //
746 // Calculate the remaining bytes of data that don't make up a full block.
747 //
748 ui32Count = ui32DataLength % 64;
749
750 //
751 // If there are bytes that do not make up a whole block, then
752 // write them separately.
753 //
754 if(ui32Count)
755 {
756 //
757 // Wait until the engine has finished processing the previous block.
758 //
759 while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) &
760 SHAMD5_INT_INPUT_READY) == 0)
761 {
762 }
763
764 //
765 // Loop through the remaining words.
766 //
767 for(ui32Idx = 0; ui32Idx < ui32Count; ui32Idx += 4)
768 {
769 //
770 // Write the word into the data register.
771 //
772 HWREG(ui32Base + SHAMD5_O_DATA_0_IN + ui32Idx) = *pui32DataSrc++;
773 }
774 }
775 }
776
777 //*****************************************************************************
778 //
779 //! Compute a hash using the SHA/MD5 module.
780 //!
781 //! \param ui32Base is the base address of the SHA/MD5 module.
782 //! \param pui32DataSrc is a pointer to an array of data that contains the
783 //! data that will be hashed.
784 //! \param ui32DataLength specifies the length of the data to be hashed in
785 //! bytes.
786 //! \param pui32HashResult is a pointer to an array that holds the result
787 //! of the hashing operation.
788 //!
789 //! This function computes the hash of an array of data using the SHA/MD5
790 //! module.
791 //!
792 //! The length of the hash result is dependent on the algorithm that is in use.
793 //! The following table shows the correct array size for each algorithm:
794 //!
795 //! -----------------------------------------
796 //! | Algorithm | Number of Words in Result |
797 //! -----------------------------------------
798 //! | MD5 | 4 Words (128 bits) |
799 //! | SHA-1 | 5 Words (160 bits) |
800 //! | SHA-224 | 7 Words (224 bits) |
801 //! | SHA-256 | 8 Words (256 bits) |
802 //! -----------------------------------------
803 //!
804 //! \return None
805 //
806 //*****************************************************************************
807 void
SHAMD5DataProcess(uint32_t ui32Base,uint32_t * pui32DataSrc,uint32_t ui32DataLength,uint32_t * pui32HashResult)808 SHAMD5DataProcess(uint32_t ui32Base, uint32_t *pui32DataSrc,
809 uint32_t ui32DataLength, uint32_t *pui32HashResult)
810 {
811 //
812 // Check the arguments.
813 //
814 ASSERT(ui32Base == SHAMD5_BASE);
815 ASSERT((ui32DataLength % 64) == 0);
816
817 //
818 // Wait for the context to be ready before writing the mode.
819 //
820 while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_CONTEXT_READY) ==
821 0)
822 {
823 }
824
825 //
826 // Write the length.
827 //
828 SHAMD5HashLengthSet(ui32Base, ui32DataLength);
829
830 //
831 // Write the data.
832 //
833 _SHAMD5DataWriteMultiple(ui32Base, pui32DataSrc, ui32DataLength);
834
835 //
836 // Wait for the output to be ready.
837 //
838 while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_OUTPUT_READY) ==
839 0)
840 {
841 }
842
843 //
844 // Read the result.
845 //
846 SHAMD5ResultRead(ui32Base, pui32HashResult);
847 }
848
849 //*****************************************************************************
850 //
851 //! Compute a HMAC with key pre-processing using the SHA/MD5 module.
852 //!
853 //! \param ui32Base is the base address of the SHA/MD5 module.
854 //! \param pui32DataSrc is a pointer to an array of data that contains the
855 //! data that is to be hashed.
856 //! \param ui32DataLength specifies the length of the data to be hashed in
857 //! bytes.
858 //! \param pui32HashResult is a pointer to an array that holds the result
859 //! of the hashing operation.
860 //!
861 //! This function computes a HMAC with the given data using the SHA/MD5
862 //! module with a preprocessed key.
863 //!
864 //! The length of the hash result is dependent on the algorithm that is
865 //! selected with the \e ui32Algo argument. The following table shows the
866 //! correct array size for each algorithm:
867 //!
868 //! -----------------------------------------
869 //! | Algorithm | Number of Words in Result |
870 //! -----------------------------------------
871 //! | MD5 | 4 Words (128 bits) |
872 //! | SHA-1 | 5 Words (160 bits) |
873 //! | SHA-224 | 7 Words (224 bits) |
874 //! | SHA-256 | 8 Words (256 bits) |
875 //! -----------------------------------------
876 //!
877 //! \return None
878 //
879 //*****************************************************************************
880 void
SHAMD5HMACProcess(uint32_t ui32Base,uint32_t * pui32DataSrc,uint32_t ui32DataLength,uint32_t * pui32HashResult)881 SHAMD5HMACProcess(uint32_t ui32Base, uint32_t *pui32DataSrc,
882 uint32_t ui32DataLength, uint32_t *pui32HashResult)
883 {
884 //
885 // Check the arguments.
886 //
887 ASSERT(ui32Base == SHAMD5_BASE);
888
889 //
890 // Wait for the context to be ready before writing the mode.
891 //
892 while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_CONTEXT_READY) ==
893 0)
894 {
895 }
896
897 //
898 // Write the length.
899 //
900 SHAMD5HashLengthSet(ui32Base, ui32DataLength);
901
902 //
903 // Write the data in the registers.
904 //
905 _SHAMD5DataWriteMultiple(ui32Base, pui32DataSrc, ui32DataLength);
906
907 //
908 // Wait for the output to be ready.
909 //
910 while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_OUTPUT_READY) ==
911 0)
912 {
913 }
914
915 //
916 // Read the result.
917 //
918 SHAMD5ResultRead(ui32Base, pui32HashResult);
919 }
920
921 //*****************************************************************************
922 //
923 //! Process an HMAC key using the SHA/MD5 module.
924 //!
925 //! \param ui32Base is the base address of the SHA/MD5 module.
926 //! \param pui32Key is a pointer to an array that contains the key to be
927 //! processed.
928 //! \param pui32PPKey is the pointer to the array that contains the
929 //! pre-processed key.
930 //!
931 //! This function processes an HMAC key using the SHA/MD5. The resultant
932 //! pre-processed key can then be used with later HMAC operations to speed
933 //! processing time.
934 //!
935 //! The \e pui32Key array must be 16 words (512 bits) long. If the key is less
936 //! than 512 bits, it must be padded with zeros. The \e pui32PPKey array must
937 //! each be 16 words (512 bits) long.
938 //!
939 //! \return None
940 //
941 //*****************************************************************************
942 void
SHAMD5HMACPPKeyGenerate(uint32_t ui32Base,uint32_t * pui32Key,uint32_t * pui32PPKey)943 SHAMD5HMACPPKeyGenerate(uint32_t ui32Base, uint32_t *pui32Key,
944 uint32_t *pui32PPKey)
945 {
946 uint32_t ui32Index;
947
948 //
949 // Check the arguments.
950 //
951 ASSERT(ui32Base == SHAMD5_BASE);
952
953 //
954 // Wait for the context to be ready before writing the mode.
955 //
956 while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_CONTEXT_READY) ==
957 0)
958 {
959 }
960
961 //
962 // Write the HMAC key.
963 //
964 for(ui32Index = 0; ui32Index < 64; ui32Index += 4)
965 {
966 HWREG(ui32Base + SHAMD5_O_ODIGEST_A + ui32Index) = *pui32Key++;
967 }
968
969 //
970 // Set the flag to cause the HMAC key to be pre-processed.
971 //
972 HWREG(ui32Base + SHAMD5_O_MODE) |= SHAMD5_MODE_HMAC_KEY_PROC;
973
974 //
975 // Set the length to zero to start the HMAC key pre-processing.
976 //
977 HWREG(ui32Base + SHAMD5_O_LENGTH) = 0;
978
979 //
980 // Wait for key to be processed.
981 //
982 while((HWREG(ui32Base + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_OUTPUT_READY) ==
983 0)
984 {
985 }
986
987 //
988 // Read the pre-processed key from the SHA/MD5 module.
989 //
990 for(ui32Index = 0; ui32Index < 64; ui32Index += 4)
991 {
992 *pui32PPKey++ = HWREG(ui32Base + SHAMD5_O_ODIGEST_A + ui32Index);
993 }
994 }
995
996 //*****************************************************************************
997 //
998 //! Writes an HMAC key to the digest registers in the SHA/MD5 module.
999 //!
1000 //! \param ui32Base is the base address of the SHA/MD5 module.
1001 //! \param pui32Src is the pointer to the 16-word array of the HMAC key.
1002 //!
1003 //! This function is used to write HMAC key to the digest registers for
1004 //! key preprocessing. The size of pui32Src must be 512 bytes. If the key is
1005 //! less than 512 bytes, then it must be padded with zeros.
1006 //!
1007 //! \note It is recommended to use the SHAMD5IntStatus() function to check
1008 //! whether the context is ready before writing the key.
1009 //!
1010 //! \return None
1011 //
1012 //*****************************************************************************
1013 void
SHAMD5HMACKeySet(uint32_t ui32Base,uint32_t * pui32Src)1014 SHAMD5HMACKeySet(uint32_t ui32Base, uint32_t *pui32Src)
1015 {
1016 uint32_t ui32Idx;
1017
1018 //
1019 // Check the arguments.
1020 //
1021 ASSERT(ui32Base == SHAMD5_BASE);
1022
1023 //
1024 // Write the key to the digest registers.
1025 //
1026 for(ui32Idx = 0; ui32Idx < 64; ui32Idx += 4)
1027 {
1028 HWREG(ui32Base + SHAMD5_O_ODIGEST_A + ui32Idx) = *pui32Src++;
1029 }
1030
1031 //
1032 // Configure the SHA engine for HMAC operation.
1033 //
1034 HWREG(ui32Base + SHAMD5_O_MODE) |= (SHAMD5_MODE_HMAC_OUTER_HASH |
1035 SHAMD5_MODE_HMAC_KEY_PROC |
1036 SHAMD5_MODE_CLOSE_HASH);
1037 }
1038
1039 //*****************************************************************************
1040 //
1041 //! Writes a pre-processed HMAC key to the digest registers in the SHA/MD5
1042 //! module.
1043 //!
1044 //! \param ui32Base is the base address of the SHA/MD5 module.
1045 //! \param pui32Src is the pointer to the 16-word array of the HMAC key.
1046 //!
1047 //! This function is used to write HMAC key to the digest registers for
1048 //! key preprocessing. The size of pui32Src must be 512 bytes. If the key is
1049 //! less than 512 bytes, then it must be padded with zeros.
1050 //!
1051 //! \note It is recommended to use the SHAMD5IntStatus() function to check
1052 //! whether the context is ready before writing the key.
1053 //!
1054 //! \return None
1055 //
1056 //*****************************************************************************
1057 void
SHAMD5HMACPPKeySet(uint32_t ui32Base,uint32_t * pui32Src)1058 SHAMD5HMACPPKeySet(uint32_t ui32Base, uint32_t *pui32Src)
1059 {
1060 uint32_t ui32Idx;
1061
1062 //
1063 // Check the arguments.
1064 //
1065 ASSERT(ui32Base == SHAMD5_BASE);
1066
1067 //
1068 // Write the key to the digest registers.
1069 //
1070 for(ui32Idx = 0; ui32Idx < 64; ui32Idx += 4)
1071 {
1072 HWREG(ui32Base + SHAMD5_O_ODIGEST_A + ui32Idx) = *pui32Src++;
1073 }
1074
1075 //
1076 // Configure the SHA engine to continue the HMAC.
1077 //
1078 HWREG(ui32Base + SHAMD5_O_MODE) |= (SHAMD5_MODE_HMAC_OUTER_HASH |
1079 SHAMD5_MODE_CLOSE_HASH);
1080
1081 //
1082 // Write the digest count to 64 to account for the preprocessed key.
1083 //
1084 HWREG(ui32Base + SHAMD5_O_DIGEST_COUNT) = 64;
1085 }
1086
1087 //*****************************************************************************
1088 //
1089 // Close the Doxygen group.
1090 //! @}
1091 //
1092 //*****************************************************************************
1093