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