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