1 /******************************************************************************
2 *  Filename:       crypto.c
3 *  Revised:        2015-11-16 19:41:47 +0100 (Mon, 16 Nov 2015)
4 *  Revision:       45094
5 *
6 *  Description:    Driver for the Crypto module
7 *
8 *  Copyright (c) 2015, Texas Instruments Incorporated
9 *  All rights reserved.
10 *
11 *  Redistribution and use in source and binary forms, with or without
12 *  modification, are permitted provided that the following conditions are met:
13 *
14 *  1) Redistributions of source code must retain the above copyright notice,
15 *     this list of conditions and the following disclaimer.
16 *
17 *  2) Redistributions in binary form must reproduce the above copyright notice,
18 *     this list of conditions and the following disclaimer in the documentation
19 *     and/or other materials provided with the distribution.
20 *
21 *  3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 *     be used to endorse or promote products derived from this software without
23 *     specific prior written permission.
24 *
25 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 *  POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38 
39 #include <driverlib/crypto.h>
40 
41 //*****************************************************************************
42 //
43 // Handle support for DriverLib in ROM:
44 // This section will undo prototype renaming made in the header file
45 //
46 //*****************************************************************************
47 #if !defined(DOXYGEN)
48     #undef  CRYPTOAesLoadKey
49     #define CRYPTOAesLoadKey                NOROM_CRYPTOAesLoadKey
50     #undef  CRYPTOAesEcb
51     #define CRYPTOAesEcb                    NOROM_CRYPTOAesEcb
52     #undef  CRYPTOAesEcbStatus
53     #define CRYPTOAesEcbStatus              NOROM_CRYPTOAesEcbStatus
54     #undef  CRYPTOCcmAuthEncrypt
55     #define CRYPTOCcmAuthEncrypt            NOROM_CRYPTOCcmAuthEncrypt
56     #undef  CRYPTOCcmAuthEncryptStatus
57     #define CRYPTOCcmAuthEncryptStatus      NOROM_CRYPTOCcmAuthEncryptStatus
58     #undef  CRYPTOCcmAuthEncryptResultGet
59     #define CRYPTOCcmAuthEncryptResultGet   NOROM_CRYPTOCcmAuthEncryptResultGet
60     #undef  CRYPTOCcmInvAuthDecrypt
61     #define CRYPTOCcmInvAuthDecrypt         NOROM_CRYPTOCcmInvAuthDecrypt
62     #undef  CRYPTOCcmInvAuthDecryptStatus
63     #define CRYPTOCcmInvAuthDecryptStatus   NOROM_CRYPTOCcmInvAuthDecryptStatus
64     #undef  CRYPTOCcmInvAuthDecryptResultGet
65     #define CRYPTOCcmInvAuthDecryptResultGet NOROM_CRYPTOCcmInvAuthDecryptResultGet
66     #undef  CRYPTODmaEnable
67     #define CRYPTODmaEnable                 NOROM_CRYPTODmaEnable
68     #undef  CRYPTODmaDisable
69     #define CRYPTODmaDisable                NOROM_CRYPTODmaDisable
70 #endif
71 
72 //*****************************************************************************
73 //
74 // Current AES operation initialized to None
75 //
76 //*****************************************************************************
77 volatile uint32_t g_ui32CurrentAesOp = CRYPTO_AES_NONE;
78 
79 //*****************************************************************************
80 //
81 //! Write the key into the Key Ram.
82 //
83 //*****************************************************************************
84 uint32_t
CRYPTOAesLoadKey(uint32_t * pui32AesKey,uint32_t ui32KeyLocation)85 CRYPTOAesLoadKey(uint32_t *pui32AesKey,
86                  uint32_t ui32KeyLocation)
87 {
88     //
89     // Check the arguments.
90     //
91     ASSERT((ui32KeyLocation == CRYPTO_KEY_AREA_0) |
92            (ui32KeyLocation == CRYPTO_KEY_AREA_1) |
93            (ui32KeyLocation == CRYPTO_KEY_AREA_2) |
94            (ui32KeyLocation == CRYPTO_KEY_AREA_3) |
95            (ui32KeyLocation == CRYPTO_KEY_AREA_4) |
96            (ui32KeyLocation == CRYPTO_KEY_AREA_5) |
97            (ui32KeyLocation == CRYPTO_KEY_AREA_6) |
98            (ui32KeyLocation == CRYPTO_KEY_AREA_7));
99 
100     //
101     // Set current operating state of the Crypto module.
102     //
103     g_ui32CurrentAesOp = CRYPTO_AES_KEYL0AD;
104 
105     //
106     // Disable the external interrupt to stop the interrupt form propagating
107     // from the module to the System CPU.
108     //
109     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
110 
111     //
112     // Enable internal interrupts.
113     //
114     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_INT_LEVEL;
115     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE |
116                                            CRYPTO_IRQEN_RESULT_AVAIL;
117 
118     //
119     // Configure master control module.
120     //
121     HWREGBITW(CRYPTO_BASE + CRYPTO_O_ALGSEL, CRYPTO_ALGSEL_KEY_STORE_BITN) = 1;
122 
123     //
124     // Clear any outstanding events.
125     //
126     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
127                                             CRYPTO_IRQCLR_RESULT_AVAIL);
128 
129     //
130     // Configure key store module for 128 bit operation.
131     //
132     HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE) &= ~CRYPTO_KEYSIZE_SIZE_M;
133     HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE) |= KEY_STORE_SIZE_128;
134 
135     //
136     // Enable keys to write (e.g. Key 0).
137     //
138     HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITEAREA) = (0x00000001 << ui32KeyLocation);
139 
140     //
141     // Enable Crypto DMA channel 0.
142     //
143     HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
144 
145     //
146     // Base address of the key in ext. memory.
147     //
148     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32AesKey;
149 
150     //
151     // Total key length in bytes (e.g. 16 for 1 x 128-bit key).
152     // Writing the length of the key enables the DMA operation.
153     //
154     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = KEY_BLENGTH;
155 
156     //
157     // Wait for the DMA operation to complete.
158     //
159     do
160     {
161         CPUdelay(1);
162     }
163     while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & 0x00000001));
164 
165     //
166     // Check for errors in DMA and key store.
167     //
168     if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) &
169             (CRYPTO_IRQSTAT_DMA_BUS_ERR |
170              CRYPTO_IRQSTAT_KEY_ST_WR_ERR)) == 0)
171     {
172         //
173         // Acknowledge/clear the interrupt and disable the master control.
174         //
175         HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
176                                                 CRYPTO_IRQCLR_RESULT_AVAIL);
177         HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = 0x00000000;
178 
179         //
180         // Check status, if error return error code.
181         //
182         if(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) != (0x00000001 << ui32KeyLocation))
183         {
184             g_ui32CurrentAesOp = CRYPTO_AES_NONE;
185             return (AES_KEYSTORE_READ_ERROR);
186         }
187     }
188 
189     //
190     // Return success.
191     //
192     g_ui32CurrentAesOp = CRYPTO_AES_NONE;
193     return (AES_SUCCESS);
194 }
195 
196 //*****************************************************************************
197 //
198 //! Start an AES-ECB operation (encryption or decryption).
199 //
200 //*****************************************************************************
201 uint32_t
CRYPTOAesEcb(uint32_t * pui32MsgIn,uint32_t * pui32MsgOut,uint32_t ui32KeyLocation,bool bEncrypt,bool bIntEnable)202 CRYPTOAesEcb(uint32_t *pui32MsgIn, uint32_t *pui32MsgOut,
203              uint32_t ui32KeyLocation, bool bEncrypt,
204              bool bIntEnable)
205 {
206     //
207     // Set current operating state of the Crypto module.
208     //
209     g_ui32CurrentAesOp = CRYPTO_AES_ECB;
210 
211     //
212     // Enable internal interrupts.
213     //
214     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_INT_LEVEL;
215     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL;
216 
217     //
218     // Clear any outstanding interrupts.
219     //
220     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
221                                             CRYPTO_IRQCLR_RESULT_AVAIL);
222 
223     //
224     // If using interrupts clear any pending interrupts and enable interrupts
225     // for the Crypto module.
226     //
227     if(bIntEnable)
228     {
229         IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ);
230         IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
231     }
232 
233     //
234     // Configure Master Control module.
235     //
236     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES;
237 
238     //
239     //
240     //
241     HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation;
242 
243     //
244     //Wait until key is loaded to the AES module.
245     //
246     do
247     {
248         CPUdelay(1);
249     }
250     while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY));
251 
252     //
253     // Check for Key store Read error.
254     //
255     if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR))
256     {
257         return (AES_KEYSTORE_READ_ERROR);
258     }
259 
260     //
261     // Configure AES engine (program AES-ECB-128 encryption and no
262     // initialization vector - IV).
263     //
264     if(bEncrypt)
265     {
266         HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = CRYPTO_AES128_ENCRYPT;
267     }
268     else
269     {
270         HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = CRYPTO_AES128_DECRYPT;
271     }
272 
273     //
274     // Write the length of the data.
275     //
276     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = AES_ECB_LENGTH;
277     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1) = 0;
278 
279     //
280     // Enable Crypto DMA channel 0.
281     //
282     HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
283 
284     //
285     // Base address of the input data in ext. memory.
286     //
287     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32MsgIn;
288 
289     //
290     // Input data length in bytes, equal to the message.
291     //
292     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = AES_ECB_LENGTH;
293 
294     //
295     // Enable Crypto DMA channel 1.
296     //
297     HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
298 
299     //
300     // Set up the address and length of the output data.
301     //
302     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) = (uint32_t)pui32MsgOut;
303     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = AES_ECB_LENGTH;
304 
305     //
306     // Return success
307     //
308     return AES_SUCCESS;
309 }
310 
311 //*****************************************************************************
312 //
313 //! Check the result of an AES ECB operation
314 //
315 //*****************************************************************************
316 uint32_t
CRYPTOAesEcbStatus(void)317 CRYPTOAesEcbStatus(void)
318 {
319     uint32_t ui32Status;
320 
321     //
322     // Get the current DMA status.
323     //
324     ui32Status = HWREG(CRYPTO_BASE + CRYPTO_O_DMASTAT);
325 
326     //
327     // Check if DMA is still busy.
328     //
329     if(ui32Status & CRYPTO_DMA_BSY)
330     {
331         return (AES_DMA_BSY);
332     }
333 
334     //
335     // Check the status of the DMA operation - return error if not success.
336     //
337     if(ui32Status & CRYPTO_DMA_BUS_ERROR)
338     {
339         g_ui32CurrentAesOp = CRYPTO_AES_NONE;
340         return (AES_DMA_BUS_ERROR);
341     }
342 
343     //
344     // Operation successful - disable interrupt and return success.
345     //
346     g_ui32CurrentAesOp = CRYPTO_AES_NONE;
347     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
348     return (AES_SUCCESS);
349 }
350 
351 //*****************************************************************************
352 //
353 //! Start CCM operation
354 //
355 //*****************************************************************************
356 uint32_t
CRYPTOCcmAuthEncrypt(bool bEncrypt,uint32_t ui32AuthLength,uint32_t * pui32Nonce,uint32_t * pui32PlainText,uint32_t ui32PlainTextLength,uint32_t * pui32Header,uint32_t ui32HeaderLength,uint32_t ui32KeyLocation,uint32_t ui32FieldLength,bool bIntEnable)357 CRYPTOCcmAuthEncrypt(bool bEncrypt, uint32_t ui32AuthLength ,
358                      uint32_t *pui32Nonce, uint32_t *pui32PlainText,
359                      uint32_t ui32PlainTextLength, uint32_t *pui32Header,
360                      uint32_t ui32HeaderLength, uint32_t ui32KeyLocation,
361                      uint32_t ui32FieldLength, bool bIntEnable)
362 {
363     uint32_t ui32CtrlVal;
364     uint32_t i;
365     uint32_t *pui32CipherText;
366     union {
367         uint32_t w[4];
368         uint8_t  b[16];
369     } ui8InitVec;
370 
371     //
372     // Input address for the encryption engine is the same as the output.
373     //
374     pui32CipherText = pui32PlainText;
375 
376     //
377     // Set current operating state of the Crypto module.
378     //
379     g_ui32CurrentAesOp = CRYPTO_AES_CCM;
380 
381     //
382     // Disable global interrupt, enable local interrupt and clear any pending
383     // interrupts.
384     //
385     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
386     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
387                                             CRYPTO_IRQCLR_RESULT_AVAIL);
388 
389     //
390     // Enable internal interrupts.
391     //
392     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_INT_LEVEL;
393     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE |
394                                            CRYPTO_IRQCLR_RESULT_AVAIL;
395 
396     //
397     // Configure master control module for AES operation.
398     //
399     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES;
400 
401     //
402     // Enable keys to read (e.g. Key 0).
403     //
404     HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation;
405 
406     //
407     // Wait until key is loaded to the AES module.
408     //
409     do
410     {
411         CPUdelay(1);
412     }
413     while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY));
414 
415     //
416     // Check for Key store Read error.
417     //
418     if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR))
419     {
420         return (AES_KEYSTORE_READ_ERROR);
421     }
422 
423     //
424     // Prepare the initialization vector (IV),
425     // Length of Nonce l(n) = 15 - ui32FieldLength.
426     //
427     ui8InitVec.b[0] = ui32FieldLength - 1;
428     for(i = 0; i < 12; i++)
429     {
430         ui8InitVec.b[i + 1] = ((uint8_t*)pui32Nonce)[i];
431     }
432     if(ui32FieldLength == 2)
433     {
434         ui8InitVec.b[13] = ((uint8_t*)pui32Nonce)[12];
435     }
436     else
437     {
438         ui8InitVec.b[13] = 0;
439     }
440     ui8InitVec.b[14] = 0;
441     ui8InitVec.b[15] = 0;
442 
443     //
444     // Write initialization vector.
445     //
446     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = ui8InitVec.w[0];
447     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = ui8InitVec.w[1];
448     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = ui8InitVec.w[2];
449     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = ui8InitVec.w[3];
450 
451     //
452     // Configure AES engine.
453     //
454     ui32CtrlVal = ((ui32FieldLength - 1) << CRYPTO_AESCTL_CCM_L_S);
455     if ( ui32AuthLength >= 2 ) {
456         ui32CtrlVal |= ((( ui32AuthLength - 2 ) >> 1 ) << CRYPTO_AESCTL_CCM_M_S );
457     }
458     ui32CtrlVal |= CRYPTO_AESCTL_CCM;
459     ui32CtrlVal |= CRYPTO_AESCTL_CTR;
460     ui32CtrlVal |= CRYPTO_AESCTL_SAVE_CONTEXT;
461     ui32CtrlVal |= (KEY_STORE_SIZE_128 << CRYPTO_AESCTL_KEY_SIZE_S);
462     ui32CtrlVal |= (1 << CRYPTO_AESCTL_DIR_S);
463     ui32CtrlVal |= (CRYPTO_AES_CTR_128 << CRYPTO_AESCTL_CTR_WIDTH_S);
464 
465     //
466     // Write the configuration for 128 bit AES-CCM.
467     //
468     HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ui32CtrlVal;
469 
470     //
471     // Write the length of the crypto block (plain text).
472     // Low and high part (high part is assumed to be always 0).
473     //
474     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = ui32PlainTextLength;
475     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1)  =  0;
476 
477     //
478     // Write the length of the header field.
479     // Also called AAD - Additional Authentication Data.
480     //
481     HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN) = ui32HeaderLength;
482 
483     //
484     // Check if any header information (AAD).
485     // If so configure the DMA controller to fetch the header.
486     //
487     if(ui32HeaderLength != 0)
488     {
489         //
490         // Enable DMA channel 0.
491         //
492         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
493 
494         //
495         // Register the base address of the header (AAD).
496         //
497         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32Header;
498 
499         //
500         // Header length in bytes (may be non-block size aligned).
501         //
502         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32HeaderLength;
503 
504         //
505         // Wait for completion of the header data transfer, DMA_IN_DONE.
506         //
507         do
508         {
509             CPUdelay(1);
510         }
511         while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_DMA_IN_DONE));
512 
513         //
514         // Check for DMA errors.
515         //
516         if(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_DMA_BUS_ERR)
517         {
518             return AES_DMA_BUS_ERROR;
519         }
520     }
521 
522     //
523     // Clear interrupt status.
524     //
525     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
526                                             CRYPTO_IRQCLR_RESULT_AVAIL);
527 
528     //
529     // Is using interrupts enable globally.
530     //
531     if(bIntEnable)
532     {
533         IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ);
534         IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
535     }
536 
537     //
538     // Enable interrupts locally.
539     //
540     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_RESULT_RDY;
541 
542     //
543     // Perform encryption if requested.
544     //
545     if(bEncrypt)
546     {
547         //
548         // Configure the DMA controller - enable both DMA channels.
549         //
550         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
551         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
552 
553         //
554         // base address of the payload data in ext. memory.
555         //
556         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) =
557             (uint32_t)pui32PlainText;
558 
559         //
560         // Payload data length in bytes, equal to the plaintext length.
561         //
562         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32PlainTextLength;
563 
564         //
565         // Enable DMA channel 1
566         //
567         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;  // Redundant (see above)?
568 
569         //
570         // Base address of the output data buffer.
571         //
572         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) =
573             (uint32_t)pui32CipherText;
574 
575         //
576         // Output data length in bytes, equal to the plaintext length.
577         //
578         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = ui32PlainTextLength;
579     }
580 
581     return AES_SUCCESS;
582 }
583 
584 //*****************************************************************************
585 //
586 //! Check the result of an AES CCM operation.
587 //
588 //*****************************************************************************
589 uint32_t
CRYPTOCcmAuthEncryptStatus(void)590 CRYPTOCcmAuthEncryptStatus(void)
591 {
592     uint32_t ui32Status;
593 
594     //
595     // Get the current DMA status.
596     //
597     ui32Status = HWREG(CRYPTO_BASE + CRYPTO_O_DMASTAT);
598 
599     //
600     // Check if DMA is still busy.
601     //
602     if(ui32Status & CRYPTO_DMA_BSY)
603     {
604         return (AES_DMA_BSY);
605     }
606 
607     //
608     // Check the status of the DMA operation - return error if not success.
609     //
610     if(ui32Status & CRYPTO_DMA_BUS_ERROR)
611     {
612         g_ui32CurrentAesOp = CRYPTO_AES_NONE;
613         return (AES_DMA_BUS_ERROR);
614     }
615 
616     //
617     // Operation successful - disable interrupt and return success.
618     //
619     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
620     return (AES_SUCCESS);
621 }
622 
623 //*****************************************************************************
624 //
625 //! Get the result of an AES-CCM operation
626 //
627 //*****************************************************************************
628 uint32_t
CRYPTOCcmAuthEncryptResultGet(uint32_t ui32TagLength,uint32_t * pui32CcmTag)629 CRYPTOCcmAuthEncryptResultGet(uint32_t ui32TagLength, uint32_t *pui32CcmTag)
630 {
631     uint32_t volatile ui32Tag[4];
632     uint32_t ui32Idx;
633 
634     //
635     // Result has already been copied to the output buffer by DMA
636     // Disable master control.
637     //
638     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = 0x00000000;
639 
640     //
641     // Read tag - wait for the context ready bit.
642     //
643     do
644     {
645         CPUdelay(1);
646     }
647     while(!(HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) &
648             CRYPTO_AESCTL_SAVED_CONTEXT_RDY));
649 
650     //
651     // Read the Tag registers.
652     //
653     ui32Tag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0);
654     ui32Tag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1);
655     ui32Tag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2);
656     ui32Tag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3);
657 
658     for(ui32Idx = 0; ui32Idx < ui32TagLength ; ui32Idx++)
659     {
660         *((uint8_t*)pui32CcmTag + ui32Idx) = *((uint8_t*)ui32Tag + ui32Idx);
661     }
662 
663     //
664     // Operation successful -  clear interrupt status.
665     //
666     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
667                                             CRYPTO_IRQCLR_RESULT_AVAIL);
668     g_ui32CurrentAesOp = CRYPTO_AES_NONE;
669     return AES_SUCCESS;
670 }
671 
672 //*****************************************************************************
673 //
674 //! Start a CCM Decryption and Inverse Authentication operation.
675 //
676 //*****************************************************************************
677 uint32_t
CRYPTOCcmInvAuthDecrypt(bool bDecrypt,uint32_t ui32AuthLength,uint32_t * pui32Nonce,uint32_t * pui32CipherText,uint32_t ui32CipherTextLength,uint32_t * pui32Header,uint32_t ui32HeaderLength,uint32_t ui32KeyLocation,uint32_t ui32FieldLength,bool bIntEnable)678 CRYPTOCcmInvAuthDecrypt(bool bDecrypt, uint32_t ui32AuthLength,
679                         uint32_t *pui32Nonce, uint32_t *pui32CipherText,
680                         uint32_t ui32CipherTextLength,
681                         uint32_t *pui32Header, uint32_t ui32HeaderLength,
682                         uint32_t ui32KeyLocation,
683                         uint32_t ui32FieldLength, bool bIntEnable)
684 {
685     uint32_t ui32CtrlVal;
686     uint32_t i;
687     uint32_t *pui32PlainText;
688     uint32_t ui32CryptoBlockLength;
689     union {
690         uint32_t w[4];
691         uint8_t  b[16];
692     } ui8InitVec;
693 
694     //
695     // Input address for the encryption engine is the same as the output.
696     //
697     pui32PlainText = pui32CipherText;
698 
699     //
700     // Set current operating state of the Crypto module.
701     //
702     g_ui32CurrentAesOp = CRYPTO_AES_CCM;
703 
704     //
705     // Disable global interrupt, enable local interrupt and clear any pending.
706     // interrupts.
707     //
708     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
709     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
710                                             CRYPTO_IRQCLR_RESULT_AVAIL);
711     //
712     // Enable internal interrupts.
713     //
714     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_INT_LEVEL;
715     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE |
716                                            CRYPTO_IRQCLR_RESULT_AVAIL;
717 
718     //
719     // Configure master control module for AES operation.
720     //
721     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES;
722 
723     //
724     // Enable keys to read (e.g. Key 0).
725     //
726     HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation;
727 
728     //
729     // Wait until key is loaded to the AES module.
730     //
731     do
732     {
733         CPUdelay(1);
734     }
735     while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY));
736 
737     //
738     // Check for Key store Read error.
739     //
740     if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR))
741     {
742         return (AES_KEYSTORE_READ_ERROR);
743     }
744 
745     //
746     // Prepare the initialization vector (IV),
747     // Length of Nonce l(n) = 15 - ui32FieldLength.
748     //
749     ui8InitVec.b[0] = ui32FieldLength - 1;
750     for(i = 0; i < 12; i++)
751     {
752         ui8InitVec.b[i + 1] = ((uint8_t*)pui32Nonce)[i];
753     }
754     if(ui32FieldLength == 2)
755     {
756         ui8InitVec.b[13] = ((uint8_t*)pui32Nonce)[12];
757     }
758     else
759     {
760         ui8InitVec.b[13] = 0;
761     }
762     ui8InitVec.b[14] = 0;
763     ui8InitVec.b[15] = 0;
764 
765     //
766     // Write initialization vector.
767     //
768     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = ui8InitVec.w[0];
769     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = ui8InitVec.w[1];
770     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = ui8InitVec.w[2];
771     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = ui8InitVec.w[3];
772 
773     //
774     // Configure AES engine
775     //
776     ui32CryptoBlockLength = ui32CipherTextLength - ui32AuthLength;
777     ui32CtrlVal = ((ui32FieldLength - 1) << CRYPTO_AESCTL_CCM_L_S);
778     if ( ui32AuthLength >= 2 ) {
779         ui32CtrlVal |= ((( ui32AuthLength - 2 ) >> 1 ) << CRYPTO_AESCTL_CCM_M_S );
780     }
781     ui32CtrlVal |= CRYPTO_AESCTL_CCM;
782     ui32CtrlVal |= CRYPTO_AESCTL_CTR;
783     ui32CtrlVal |= CRYPTO_AESCTL_SAVE_CONTEXT;
784     ui32CtrlVal |= (KEY_STORE_SIZE_128 << CRYPTO_AESCTL_KEY_SIZE_S);
785     ui32CtrlVal |= (0 << CRYPTO_AESCTL_DIR_S);
786     ui32CtrlVal |= (CRYPTO_AES_CTR_128 << CRYPTO_AESCTL_CTR_WIDTH_S);
787 
788     //
789     // Write the configuration for 128 bit AES-CCM.
790     //
791     HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ui32CtrlVal;
792 
793     //
794     // Write the length of the crypto block (plain text).
795     // Low and high part (high part is assumed to be always 0).
796     //
797     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = ui32CryptoBlockLength;
798     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1)  =  0;
799 
800     //
801     // Write the length of the header field.
802     // Also called AAD - Additional Authentication Data.
803     //
804     HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN) = ui32HeaderLength;
805 
806     //
807     // Check if any header information (AAD).
808     // If so configure the DMA controller to fetch the header.
809     //
810     if(ui32HeaderLength != 0)
811     {
812         //
813         // Enable DMA channel 0.
814         //
815         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
816 
817         //
818         // Register the base address of the header (AAD).
819         //
820         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32Header;
821 
822         //
823         // Header length in bytes (may be non-block size aligned).
824         //
825         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32HeaderLength;
826 
827         //
828         // Wait for completion of the header data transfer, DMA_IN_DONE.
829         //
830         do
831         {
832             CPUdelay(1);
833         }
834         while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_DMA_IN_DONE));
835 
836         //
837         // Check for DMA errors.
838         //
839         if(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_DMA_BUS_ERR)
840         {
841             return AES_DMA_BUS_ERROR;
842         }
843     }
844 
845     //
846     // Clear interrupt status.
847     //
848     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
849                                             CRYPTO_IRQCLR_RESULT_AVAIL);
850 
851     //
852     // Is using interrupts - clear and enable globally.
853     //
854     if(bIntEnable)
855     {
856         IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ);
857         IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
858     }
859 
860     //
861     // Enable internal interrupts.
862     //
863     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_INT_LEVEL;
864     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL;
865 
866     //
867     // Perform decryption if requested.
868     //
869     if(bDecrypt)
870     {
871         //
872         // Configure the DMA controller - enable both DMA channels.
873         //
874         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
875 
876         //
877         // Base address of the payload data in ext. memory.
878         //
879         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) =
880             (uint32_t)pui32CipherText;
881 
882         //
883         // Payload data length in bytes, equal to the cipher text length.
884         //
885         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32CryptoBlockLength;
886 
887         //
888         // Enable DMA channel 1.
889         //
890         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
891 
892         //
893         // Base address of the output data buffer.
894         //
895         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) =
896             (uint32_t)pui32PlainText;
897 
898         //
899         // Output data length in bytes, equal to the cipher text length.
900         //
901         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = ui32CryptoBlockLength;
902     }
903 
904     return AES_SUCCESS;
905 }
906 
907 //*****************************************************************************
908 //
909 //! Checks CCM decrypt and Inverse Authentication result.
910 //
911 //*****************************************************************************
912 uint32_t
CRYPTOCcmInvAuthDecryptStatus(void)913 CRYPTOCcmInvAuthDecryptStatus(void)
914 {
915     uint32_t ui32Status;
916 
917     //
918     // Get the current DMA status.
919     //
920     ui32Status = HWREG(CRYPTO_BASE + CRYPTO_O_DMASTAT);
921 
922     //
923     // Check if DMA is still busy.
924     //
925     if(ui32Status & CRYPTO_DMA_BSY)
926     {
927         return (AES_DMA_BSY);
928     }
929 
930     //
931     // Check the status of the DMA operation - return error if not success.
932     //
933     if(ui32Status & CRYPTO_DMA_BUS_ERROR)
934     {
935         g_ui32CurrentAesOp = CRYPTO_AES_NONE;
936         return (AES_DMA_BUS_ERROR);
937     }
938 
939     //
940     // Operation successful - disable interrupt and return success
941     //
942     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
943     return (AES_SUCCESS);
944 }
945 
946 //*****************************************************************************
947 //
948 //! Get the result of the CCM operation.
949 //
950 //*****************************************************************************
951 uint32_t
CRYPTOCcmInvAuthDecryptResultGet(uint32_t ui32AuthLength,uint32_t * pui32CipherText,uint32_t ui32CipherTextLength,uint32_t * pui32CcmTag)952 CRYPTOCcmInvAuthDecryptResultGet(uint32_t ui32AuthLength,
953                                  uint32_t *pui32CipherText,
954                                  uint32_t ui32CipherTextLength,
955                                  uint32_t *pui32CcmTag)
956 {
957     uint32_t volatile ui32Tag[4];
958     uint32_t ui32TagIndex;
959     uint32_t i;
960     uint32_t ui32Idx;
961 
962     ui32TagIndex = ui32CipherTextLength - ui32AuthLength;
963 
964     //
965     // Result has already been copied to the output buffer by DMA
966     // Disable master control.
967     //
968     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = 0x00000000;
969 
970     //
971     // Read tag - wait for the context ready bit.
972     //
973     do
974     {
975         CPUdelay(1);
976     }
977     while(!(HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) &
978             CRYPTO_AESCTL_SAVED_CONTEXT_RDY));
979 
980     //
981     // Read the Tag registers.
982     //
983     ui32Tag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0);
984     ui32Tag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1);
985     ui32Tag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2);
986     ui32Tag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3);
987 
988     for(ui32Idx = 0; ui32Idx < ui32AuthLength ; ui32Idx++)
989     {
990         *((uint8_t*)pui32CcmTag + ui32Idx) = *((uint8_t*)ui32Tag + ui32Idx);
991     }
992 
993     //
994     // Operation successful -  clear interrupt status.
995     //
996     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
997                                             CRYPTO_IRQCLR_RESULT_AVAIL);
998 
999     //
1000     // Verify the Tag.
1001     //
1002     for(i = 0; i < ui32AuthLength; i++)
1003     {
1004         if(*((uint8_t *)pui32CcmTag + i) !=
1005             (*((uint8_t *)pui32CipherText + ui32TagIndex + i)))
1006         {
1007             return CCM_AUTHENTICATION_FAILED;
1008         }
1009     }
1010 
1011     g_ui32CurrentAesOp = CRYPTO_AES_NONE;
1012     return AES_SUCCESS;
1013 }
1014 
1015 //*****************************************************************************
1016 //
1017 //! Enable Crypto DMA operation
1018 //
1019 //*****************************************************************************
1020 void
CRYPTODmaEnable(uint32_t ui32Channels)1021 CRYPTODmaEnable(uint32_t ui32Channels)
1022 {
1023     //
1024     // Check the arguments.
1025     //
1026     ASSERT((ui32Channels & CRYPTO_DMA_CHAN0) |
1027            (ui32Channels & CRYPTO_DMA_CHAN1));
1028 
1029     //
1030     // Enable the selected channels,
1031     //
1032     if(ui32Channels & CRYPTO_DMA_CHAN0)
1033     {
1034         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
1035     }
1036     if(ui32Channels & CRYPTO_DMA_CHAN1)
1037     {
1038         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
1039     }
1040 }
1041 
1042 //*****************************************************************************
1043 //
1044 //! Disable Crypto DMA operation
1045 //
1046 //*****************************************************************************
1047 void
CRYPTODmaDisable(uint32_t ui32Channels)1048 CRYPTODmaDisable(uint32_t ui32Channels)
1049 {
1050     //
1051     // Check the arguments.
1052     //
1053     ASSERT((ui32Channels & CRYPTO_DMA_CHAN0) |
1054            (ui32Channels & CRYPTO_DMA_CHAN1));
1055 
1056     //
1057     // Enable the selected channels.
1058     //
1059     if(ui32Channels & CRYPTO_DMA_CHAN0)
1060     {
1061         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 0;
1062     }
1063     if(ui32Channels & CRYPTO_DMA_CHAN1)
1064     {
1065         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 0;
1066     }
1067 }
1068