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