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