1 /******************************************************************************
2 *  Filename:       crypto.c
3 *  Revised:        2020-01-07 14:06:28 +0100 (Tue, 07 Jan 2020)
4 *  Revision:       56632
5 *
6 *  Description:    Driver for the Crypto module
7 *
8 *  Copyright (c) 2015 - 2017, 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 "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  CRYPTOAesCbc
51     #define CRYPTOAesCbc                    NOROM_CRYPTOAesCbc
52     #undef  CRYPTOAesCbcStatus
53     #define CRYPTOAesCbcStatus              NOROM_CRYPTOAesCbcStatus
54     #undef  CRYPTOAesEcb
55     #define CRYPTOAesEcb                    NOROM_CRYPTOAesEcb
56     #undef  CRYPTOAesEcbStatus
57     #define CRYPTOAesEcbStatus              NOROM_CRYPTOAesEcbStatus
58     #undef  CRYPTOCcmAuthEncrypt
59     #define CRYPTOCcmAuthEncrypt            NOROM_CRYPTOCcmAuthEncrypt
60     #undef  CRYPTOCcmAuthEncryptStatus
61     #define CRYPTOCcmAuthEncryptStatus      NOROM_CRYPTOCcmAuthEncryptStatus
62     #undef  CRYPTOCcmAuthEncryptResultGet
63     #define CRYPTOCcmAuthEncryptResultGet   NOROM_CRYPTOCcmAuthEncryptResultGet
64     #undef  CRYPTOCcmInvAuthDecrypt
65     #define CRYPTOCcmInvAuthDecrypt         NOROM_CRYPTOCcmInvAuthDecrypt
66     #undef  CRYPTOCcmInvAuthDecryptStatus
67     #define CRYPTOCcmInvAuthDecryptStatus   NOROM_CRYPTOCcmInvAuthDecryptStatus
68     #undef  CRYPTOCcmInvAuthDecryptResultGet
69     #define CRYPTOCcmInvAuthDecryptResultGet NOROM_CRYPTOCcmInvAuthDecryptResultGet
70     #undef  CRYPTODmaEnable
71     #define CRYPTODmaEnable                 NOROM_CRYPTODmaEnable
72     #undef  CRYPTODmaDisable
73     #define CRYPTODmaDisable                NOROM_CRYPTODmaDisable
74 #endif
75 
76 //*****************************************************************************
77 //
78 // Write the key into the Key Ram.
79 //
80 //*****************************************************************************
81 uint32_t
CRYPTOAesLoadKey(uint32_t * pui32AesKey,uint32_t ui32KeyLocation)82 CRYPTOAesLoadKey(uint32_t *pui32AesKey,
83                  uint32_t ui32KeyLocation)
84 {
85     uint32_t returnStatus = AES_KEYSTORE_READ_ERROR;
86 
87     // Check the arguments.
88     ASSERT((ui32KeyLocation == CRYPTO_KEY_AREA_0) |
89            (ui32KeyLocation == CRYPTO_KEY_AREA_1) |
90            (ui32KeyLocation == CRYPTO_KEY_AREA_2) |
91            (ui32KeyLocation == CRYPTO_KEY_AREA_3) |
92            (ui32KeyLocation == CRYPTO_KEY_AREA_4) |
93            (ui32KeyLocation == CRYPTO_KEY_AREA_5) |
94            (ui32KeyLocation == CRYPTO_KEY_AREA_6) |
95            (ui32KeyLocation == CRYPTO_KEY_AREA_7));
96 
97     // Disable the external interrupt to stop the interrupt form propagating
98     // from the module to the System CPU.
99     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
100 
101     // Clear any previously written key at the keyLocation
102     HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) = (0x00000001 << ui32KeyLocation);
103 
104     // Enable internal interrupts.
105     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL;
106     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE |
107                                           CRYPTO_IRQEN_RESULT_AVAIL;
108 
109     // Configure master control module.
110     HWREGBITW(CRYPTO_BASE + CRYPTO_O_ALGSEL, CRYPTO_ALGSEL_KEY_STORE_BITN) = 1;
111 
112     // Clear any outstanding events.
113     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
114                                             CRYPTO_IRQCLR_RESULT_AVAIL);
115 
116     // Configure key store module for 128 bit operation.
117     // Do not write to the register if the correct key size is already set.
118     // Writing to this register causes all current keys to be invalidated.
119     if (HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE) != KEY_STORE_SIZE_128) {
120         HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE) = KEY_STORE_SIZE_128;
121     }
122 
123     // Enable keys to write (e.g. Key 0).
124     HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITEAREA) = (0x00000001 << ui32KeyLocation);
125 
126     // Enable Crypto DMA channel 0.
127     HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
128 
129     // Base address of the key in ext. memory.
130     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32AesKey;
131 
132     // Total key length in bytes (e.g. 16 for 1 x 128-bit key).
133     // Writing the length of the key enables the DMA operation.
134     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = KEY_BLENGTH;
135 
136     // Wait for the DMA operation to complete.
137     do
138     {
139         CPUdelay(1);
140     }
141     while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) &
142             (CRYPTO_IRQSTAT_DMA_BUS_ERR_M |
143              CRYPTO_IRQSTAT_KEY_ST_WR_ERR_M |
144              CRYPTO_IRQSTAT_DMA_IN_DONE |
145              CRYPTO_IRQSTAT_RESULT_AVAIL_M)));
146 
147     // Check for errors in DMA and key store.
148     if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) &
149             (CRYPTO_IRQSTAT_DMA_BUS_ERR |
150              CRYPTO_IRQSTAT_KEY_ST_WR_ERR)) == 0)
151     {
152         // Acknowledge/clear the interrupt and disable the master control.
153         HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
154                                                 CRYPTO_IRQCLR_RESULT_AVAIL);
155         HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = 0x00000000;
156 
157         // Check key status, return success if key valid.
158         if(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) & (0x00000001 << ui32KeyLocation))
159         {
160             returnStatus =  AES_SUCCESS;
161         }
162     }
163 
164     // Return status.
165     return returnStatus;
166 }
167 
168 //*****************************************************************************
169 //
170 // Start an AES-CBC operation (encryption or decryption).
171 //
172 //*****************************************************************************
173 uint32_t
CRYPTOAesCbc(uint32_t * pui32MsgIn,uint32_t * pui32MsgOut,uint32_t ui32MsgLength,uint32_t * pui32Nonce,uint32_t ui32KeyLocation,bool bEncrypt,bool bIntEnable)174 CRYPTOAesCbc(uint32_t *pui32MsgIn, uint32_t *pui32MsgOut, uint32_t ui32MsgLength,
175              uint32_t *pui32Nonce, uint32_t ui32KeyLocation,
176              bool bEncrypt, bool bIntEnable)
177 {
178     uint32_t ui32CtrlVal;
179 
180     // Enable internal interrupts.
181     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL;
182     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL;
183 
184     // Clear any outstanding interrupts.
185     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
186                                             CRYPTO_IRQCLR_RESULT_AVAIL);
187 
188     // Wait for interrupt lines from module to be cleared
189     while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE | CRYPTO_IRQSTAT_RESULT_AVAIL));
190 
191     // If using interrupts clear any pending interrupts and enable interrupts
192     // for the Crypto module.
193     if(bIntEnable)
194     {
195         IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ);
196         IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
197     }
198 
199     // Configure Master Control module.
200     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES;
201 
202     // Enable keys to read (e.g. Key 0).
203     HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation;
204 
205     //Wait until key is loaded to the AES module.
206     do
207     {
208         CPUdelay(1);
209     }
210     while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY));
211 
212     // Check for Key store Read error.
213     if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR))
214     {
215         return (AES_KEYSTORE_READ_ERROR);
216     }
217 
218     // Write initialization vector.
219     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = pui32Nonce[0];
220     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = pui32Nonce[1];
221     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = pui32Nonce[2];
222     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = pui32Nonce[3];
223 
224     // Configure AES engine for AES-CBC with 128-bit key size.
225     ui32CtrlVal  = (CRYPTO_AESCTL_SAVE_CONTEXT | CRYPTO_AESCTL_CBC);
226     if(bEncrypt)
227     {
228         ui32CtrlVal |= CRYPTO_AES128_ENCRYPT;
229     }
230     else
231     {
232         ui32CtrlVal |= CRYPTO_AES128_DECRYPT;
233     }
234     HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ui32CtrlVal;
235 
236     // Write the length of the crypto block (plain text).
237     // Low and high part (high part is assumed to be always 0).
238     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = ui32MsgLength;
239     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1) = 0;
240     HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN)  = 0;
241 
242     // Enable Crypto DMA channel 0.
243     HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
244 
245     // Base address of the input data in ext. memory.
246     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32MsgIn;
247 
248     // Input data length in bytes, equal to the message.
249     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32MsgLength;
250 
251     // Enable Crypto DMA channel 1.
252     HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
253 
254     // Set up the address and length of the output data.
255     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) = (uint32_t)pui32MsgOut;
256     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = ui32MsgLength;
257 
258     // Return success
259     return AES_SUCCESS;
260 }
261 
262 //*****************************************************************************
263 //
264 // Check the result of an AES CBC operation
265 //
266 //*****************************************************************************
267 uint32_t
CRYPTOAesCbcStatus(void)268 CRYPTOAesCbcStatus(void)
269 {
270     return(CRYPTOAesEcbStatus());
271 }
272 
273 //*****************************************************************************
274 //
275 // Start an AES-ECB operation (encryption or decryption).
276 //
277 //*****************************************************************************
278 uint32_t
CRYPTOAesEcb(uint32_t * pui32MsgIn,uint32_t * pui32MsgOut,uint32_t ui32KeyLocation,bool bEncrypt,bool bIntEnable)279 CRYPTOAesEcb(uint32_t *pui32MsgIn, uint32_t *pui32MsgOut,
280              uint32_t ui32KeyLocation, bool bEncrypt,
281              bool bIntEnable)
282 {
283     // Enable internal interrupts.
284     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL;
285     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL;
286 
287     // Clear any outstanding interrupts.
288     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
289                                             CRYPTO_IRQCLR_RESULT_AVAIL);
290 
291     // Wait for interrupt lines from module to be cleared
292     while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE | CRYPTO_IRQSTAT_RESULT_AVAIL));
293 
294     // If using interrupts clear any pending interrupts and enable interrupts
295     // for the Crypto module.
296     if(bIntEnable)
297     {
298         IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ);
299         IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
300     }
301 
302     // Configure Master Control module.
303     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES;
304 
305     // Enable keys to read (e.g. Key 0).
306     HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation;
307 
308     //Wait until key is loaded to the AES module.
309     do
310     {
311         CPUdelay(1);
312     }
313     while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY));
314 
315     // Check for Key store Read error.
316     if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR))
317     {
318         return (AES_KEYSTORE_READ_ERROR);
319     }
320 
321     // Configure AES engine (program AES-ECB-128 encryption and no
322     // initialization vector - IV).
323     if(bEncrypt)
324     {
325         HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = CRYPTO_AES128_ENCRYPT;
326     }
327     else
328     {
329         HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = CRYPTO_AES128_DECRYPT;
330     }
331 
332     // Write the length of the data.
333     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = AES_ECB_LENGTH;
334     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1) = 0;
335 
336     // Enable Crypto DMA channel 0.
337     HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
338 
339     // Base address of the input data in ext. memory.
340     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32MsgIn;
341 
342     // Input data length in bytes, equal to the message.
343     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = AES_ECB_LENGTH;
344 
345     // Enable Crypto DMA channel 1.
346     HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
347 
348     // Set up the address and length of the output data.
349     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) = (uint32_t)pui32MsgOut;
350     HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = AES_ECB_LENGTH;
351 
352     // Return success
353     return AES_SUCCESS;
354 }
355 
356 //*****************************************************************************
357 //
358 // Check the result of an AES ECB operation
359 //
360 //*****************************************************************************
361 uint32_t
CRYPTOAesEcbStatus(void)362 CRYPTOAesEcbStatus(void)
363 {
364     uint32_t ui32Status;
365 
366     // Get the current DMA status.
367     ui32Status = HWREG(CRYPTO_BASE + CRYPTO_O_DMASTAT);
368 
369     // Check if DMA is still busy.
370     if(ui32Status & CRYPTO_DMA_BSY)
371     {
372         return (AES_DMA_BSY);
373     }
374 
375     // Check the status of the DMA operation - return error if not success.
376     if(ui32Status & CRYPTO_DMA_BUS_ERROR)
377     {
378         return (AES_DMA_BUS_ERROR);
379     }
380 
381     // Operation successful - disable interrupt and return success.
382     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
383     return (AES_SUCCESS);
384 }
385 
386 //*****************************************************************************
387 //
388 // Start CCM operation
389 //
390 //*****************************************************************************
391 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)392 CRYPTOCcmAuthEncrypt(bool bEncrypt, uint32_t ui32AuthLength ,
393                      uint32_t *pui32Nonce, uint32_t *pui32PlainText,
394                      uint32_t ui32PlainTextLength, uint32_t *pui32Header,
395                      uint32_t ui32HeaderLength, uint32_t ui32KeyLocation,
396                      uint32_t ui32FieldLength, bool bIntEnable)
397 {
398     uint32_t ui32CtrlVal;
399     uint32_t i;
400     uint32_t *pui32CipherText;
401     union {
402         uint32_t w[4];
403         uint8_t  b[16];
404     } ui8InitVec;
405 
406     // Input address for the encryption engine is the same as the output.
407     pui32CipherText = pui32PlainText;
408 
409     // Disable global interrupt, enable local interrupt and clear any pending
410     // interrupts.
411     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
412     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
413                                             CRYPTO_IRQCLR_RESULT_AVAIL);
414 
415     // Enable internal interrupts.
416     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL;
417     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE |
418                                           CRYPTO_IRQEN_RESULT_AVAIL;
419 
420     // Configure master control module for AES operation.
421     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES;
422 
423     // Enable keys to read (e.g. Key 0).
424     HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation;
425 
426     // Wait until key is loaded to the AES module.
427     do
428     {
429         CPUdelay(1);
430     }
431     while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY));
432 
433     // Check for Key store Read error.
434     if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR))
435     {
436         return (AES_KEYSTORE_READ_ERROR);
437     }
438 
439     // Prepare the initialization vector (IV),
440     // Length of Nonce l(n) = 15 - ui32FieldLength.
441     ui8InitVec.b[0] = ui32FieldLength - 1;
442     for(i = 0; i < 12; i++)
443     {
444         ui8InitVec.b[i + 1] = ((uint8_t*)pui32Nonce)[i];
445     }
446     if(ui32FieldLength == 2)
447     {
448         ui8InitVec.b[13] = ((uint8_t*)pui32Nonce)[12];
449     }
450     else
451     {
452         ui8InitVec.b[13] = 0;
453     }
454     ui8InitVec.b[14] = 0;
455     ui8InitVec.b[15] = 0;
456 
457     // Write initialization vector.
458     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = ui8InitVec.w[0];
459     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = ui8InitVec.w[1];
460     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = ui8InitVec.w[2];
461     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = ui8InitVec.w[3];
462 
463     // Configure AES engine.
464     ui32CtrlVal = ((ui32FieldLength - 1) << CRYPTO_AESCTL_CCM_L_S);
465     if ( ui32AuthLength >= 2 ) {
466         ui32CtrlVal |= ((( ui32AuthLength - 2 ) >> 1 ) << CRYPTO_AESCTL_CCM_M_S );
467     }
468     ui32CtrlVal |= CRYPTO_AESCTL_CCM;
469     ui32CtrlVal |= CRYPTO_AESCTL_CTR;
470     ui32CtrlVal |= CRYPTO_AESCTL_SAVE_CONTEXT;
471     ui32CtrlVal |= (KEY_STORE_SIZE_128 << CRYPTO_AESCTL_KEY_SIZE_S);
472     ui32CtrlVal |= (1 << CRYPTO_AESCTL_DIR_S);
473     ui32CtrlVal |= (CRYPTO_AES_CTR_128 << CRYPTO_AESCTL_CTR_WIDTH_S);
474 
475     // Write the configuration for 128 bit AES-CCM.
476     HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ui32CtrlVal;
477 
478     // Write the length of the crypto block (plain text).
479     // Low and high part (high part is assumed to be always 0).
480     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = ui32PlainTextLength;
481     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1)  =  0;
482 
483     // Write the length of the header field.
484     // Also called AAD - Additional Authentication Data.
485     HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN) = ui32HeaderLength;
486 
487     // Check if any header information (AAD).
488     // If so configure the DMA controller to fetch the header.
489     if(ui32HeaderLength != 0)
490     {
491         // Enable DMA channel 0.
492         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
493 
494         // Register the base address of the header (AAD).
495         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32Header;
496 
497         // Header length in bytes (may be non-block size aligned).
498         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32HeaderLength;
499 
500         // Wait for completion of the header data transfer, DMA_IN_DONE.
501         do
502         {
503             CPUdelay(1);
504         }
505         while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_IRQSTAT_DMA_IN_DONE));
506 
507         // Check for DMA errors.
508         if(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_DMA_BUS_ERR)
509         {
510             return AES_DMA_BUS_ERROR;
511         }
512     }
513 
514     // Clear interrupt status.
515     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
516                                             CRYPTO_IRQCLR_RESULT_AVAIL);
517 
518     // Wait for interrupt lines from module to be cleared
519     while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE | CRYPTO_IRQSTAT_RESULT_AVAIL));
520 
521     // Disable CRYPTO_IRQEN_DMA_IN_DONE interrupt as we only
522     // want interrupt to trigger once RESULT_AVAIL occurs.
523     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) &= ~CRYPTO_IRQEN_DMA_IN_DONE;
524 
525 
526     // Is using interrupts enable globally.
527     if(bIntEnable)
528     {
529         IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ);
530         IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
531     }
532 
533     // Enable interrupts locally.
534     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL;
535 
536     // Perform encryption if requested.
537     if(bEncrypt)
538     {
539         // Enable DMA channel 0
540         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
541 
542         // base address of the payload data in ext. memory.
543         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) =
544             (uint32_t)pui32PlainText;
545 
546         // Enable DMA channel 1
547         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
548 
549         // Base address of the output data buffer.
550         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) =
551             (uint32_t)pui32CipherText;
552 
553         // Payload data length in bytes, equal to the plaintext length.
554         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32PlainTextLength;
555         // Output data length in bytes, equal to the plaintext length.
556         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = ui32PlainTextLength;
557     }
558 
559     return AES_SUCCESS;
560 }
561 
562 //*****************************************************************************
563 //
564 // Check the result of an AES CCM operation.
565 //
566 //*****************************************************************************
567 uint32_t
CRYPTOCcmAuthEncryptStatus(void)568 CRYPTOCcmAuthEncryptStatus(void)
569 {
570     uint32_t ui32Status;
571 
572     // Get the current DMA status.
573     ui32Status = HWREG(CRYPTO_BASE + CRYPTO_O_DMASTAT);
574 
575     // Check if DMA is still busy.
576     if(ui32Status & CRYPTO_DMA_BSY)
577     {
578         return (AES_DMA_BSY);
579     }
580 
581     // Check the status of the DMA operation - return error if not success.
582     if(ui32Status & CRYPTO_DMA_BUS_ERROR)
583     {
584         return (AES_DMA_BUS_ERROR);
585     }
586 
587     // Operation successful - disable interrupt and return success.
588     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
589     return (AES_SUCCESS);
590 }
591 
592 //*****************************************************************************
593 //
594 // Get the result of an AES-CCM operation
595 //
596 //*****************************************************************************
597 uint32_t
CRYPTOCcmAuthEncryptResultGet(uint32_t ui32TagLength,uint32_t * pui32CcmTag)598 CRYPTOCcmAuthEncryptResultGet(uint32_t ui32TagLength, uint32_t *pui32CcmTag)
599 {
600     uint32_t volatile ui32Tag[4];
601     uint32_t ui32Idx;
602 
603     // Result has already been copied to the output buffer by DMA
604     // Disable master control.
605     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = 0x00000000;
606 
607     // Read tag - wait for the context ready bit.
608     do
609     {
610         CPUdelay(1);
611     }
612     while(!(HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) &
613             CRYPTO_AESCTL_SAVED_CONTEXT_RDY));
614 
615     // Read the Tag registers.
616     ui32Tag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0);
617     ui32Tag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1);
618     ui32Tag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2);
619     ui32Tag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3);
620 
621     for(ui32Idx = 0; ui32Idx < ui32TagLength ; ui32Idx++)
622     {
623         *((uint8_t*)pui32CcmTag + ui32Idx) = *((uint8_t*)ui32Tag + ui32Idx);
624     }
625 
626     // Operation successful -  clear interrupt status.
627     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
628                                             CRYPTO_IRQCLR_RESULT_AVAIL);
629     return AES_SUCCESS;
630 }
631 
632 //*****************************************************************************
633 //
634 // Start a CCM Decryption and Inverse Authentication operation.
635 //
636 //*****************************************************************************
637 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)638 CRYPTOCcmInvAuthDecrypt(bool bDecrypt, uint32_t ui32AuthLength,
639                         uint32_t *pui32Nonce, uint32_t *pui32CipherText,
640                         uint32_t ui32CipherTextLength,
641                         uint32_t *pui32Header, uint32_t ui32HeaderLength,
642                         uint32_t ui32KeyLocation,
643                         uint32_t ui32FieldLength, bool bIntEnable)
644 {
645     uint32_t ui32CtrlVal;
646     uint32_t i;
647     uint32_t *pui32PlainText;
648     uint32_t ui32CryptoBlockLength;
649     union {
650         uint32_t w[4];
651         uint8_t  b[16];
652     } ui8InitVec;
653 
654     // Input address for the encryption engine is the same as the output.
655     pui32PlainText = pui32CipherText;
656 
657     // Disable global interrupt, enable local interrupt and clear any pending.
658     // interrupts.
659     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
660     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
661                                             CRYPTO_IRQCLR_RESULT_AVAIL);
662     // Enable internal interrupts.
663     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL;
664     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_DMA_IN_DONE |
665                                           CRYPTO_IRQEN_RESULT_AVAIL;
666 
667     // Configure master control module for AES operation.
668     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = CRYPTO_ALGSEL_AES;
669 
670     // Enable keys to read (e.g. Key 0).
671     HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = ui32KeyLocation;
672 
673     // Wait until key is loaded to the AES module.
674     do
675     {
676         CPUdelay(1);
677     }
678     while((HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) & CRYPTO_KEYREADAREA_BUSY));
679 
680     // Check for Key store Read error.
681     if((HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT)& CRYPTO_KEY_ST_RD_ERR))
682     {
683         return (AES_KEYSTORE_READ_ERROR);
684     }
685 
686     // Prepare the initialization vector (IV),
687     // Length of Nonce l(n) = 15 - ui32FieldLength.
688     ui8InitVec.b[0] = ui32FieldLength - 1;
689     for(i = 0; i < 12; i++)
690     {
691         ui8InitVec.b[i + 1] = ((uint8_t*)pui32Nonce)[i];
692     }
693     if(ui32FieldLength == 2)
694     {
695         ui8InitVec.b[13] = ((uint8_t*)pui32Nonce)[12];
696     }
697     else
698     {
699         ui8InitVec.b[13] = 0;
700     }
701     ui8InitVec.b[14] = 0;
702     ui8InitVec.b[15] = 0;
703 
704     // Write initialization vector.
705     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = ui8InitVec.w[0];
706     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = ui8InitVec.w[1];
707     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = ui8InitVec.w[2];
708     HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = ui8InitVec.w[3];
709 
710     // Configure AES engine
711     ui32CryptoBlockLength = ui32CipherTextLength - ui32AuthLength;
712     ui32CtrlVal = ((ui32FieldLength - 1) << CRYPTO_AESCTL_CCM_L_S);
713     if ( ui32AuthLength >= 2 ) {
714         ui32CtrlVal |= ((( ui32AuthLength - 2 ) >> 1 ) << CRYPTO_AESCTL_CCM_M_S );
715     }
716     ui32CtrlVal |= CRYPTO_AESCTL_CCM;
717     ui32CtrlVal |= CRYPTO_AESCTL_CTR;
718     ui32CtrlVal |= CRYPTO_AESCTL_SAVE_CONTEXT;
719     ui32CtrlVal |= (KEY_STORE_SIZE_128 << CRYPTO_AESCTL_KEY_SIZE_S);
720     ui32CtrlVal |= (0 << CRYPTO_AESCTL_DIR_S);
721     ui32CtrlVal |= (CRYPTO_AES_CTR_128 << CRYPTO_AESCTL_CTR_WIDTH_S);
722 
723     // Write the configuration for 128 bit AES-CCM.
724     HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ui32CtrlVal;
725 
726     // Write the length of the crypto block (plain text).
727     // Low and high part (high part is assumed to be always 0).
728     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = ui32CryptoBlockLength;
729     HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1)  =  0;
730 
731     // Write the length of the header field.
732     // Also called AAD - Additional Authentication Data.
733     HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN) = ui32HeaderLength;
734 
735     // Check if any header information (AAD).
736     // If so configure the DMA controller to fetch the header.
737     if(ui32HeaderLength != 0)
738     {
739         // Enable DMA channel 0.
740         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
741 
742         // Register the base address of the header (AAD).
743         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)pui32Header;
744 
745         // Header length in bytes (may be non-block size aligned).
746         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32HeaderLength;
747 
748         // Wait for completion of the header data transfer, DMA_IN_DONE.
749         do
750         {
751             CPUdelay(1);
752         }
753         while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_IRQSTAT_DMA_IN_DONE));
754 
755         // Check for DMA errors.
756         if(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & CRYPTO_DMA_BUS_ERR)
757         {
758             return AES_DMA_BUS_ERROR;
759         }
760     }
761 
762     // Clear interrupt status.
763     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
764                                             CRYPTO_IRQCLR_RESULT_AVAIL);
765 
766     // Wait for interrupt lines from module to be cleared
767     while(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & (CRYPTO_IRQSTAT_DMA_IN_DONE | CRYPTO_IRQSTAT_RESULT_AVAIL));
768 
769     // Disable CRYPTO_IRQEN_DMA_IN_DONE interrupt as we only
770     // want interrupt to trigger once RESULT_AVAIL occurs.
771     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) &= ~CRYPTO_IRQEN_DMA_IN_DONE;
772 
773     // Is using interrupts - clear and enable globally.
774     if(bIntEnable)
775     {
776         IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ);
777         IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
778     }
779 
780     // Enable internal interrupts.
781     HWREG(CRYPTO_BASE + CRYPTO_O_IRQTYPE) = CRYPTO_IRQTYPE_LEVEL;
782     HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) = CRYPTO_IRQEN_RESULT_AVAIL;
783 
784     // Perform decryption if requested.
785     if(bDecrypt)
786     {
787         // Configure the DMA controller - enable both DMA channels.
788         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
789 
790         // Base address of the payload data in ext. memory.
791         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) =
792             (uint32_t)pui32CipherText;
793 
794         // Payload data length in bytes, equal to the cipher text length.
795         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = ui32CryptoBlockLength;
796 
797         // Enable DMA channel 1.
798         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
799 
800         // Base address of the output data buffer.
801         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) =
802             (uint32_t)pui32PlainText;
803 
804         // Output data length in bytes, equal to the cipher text length.
805         HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = ui32CryptoBlockLength;
806     }
807 
808     return AES_SUCCESS;
809 }
810 
811 //*****************************************************************************
812 //
813 // Checks CCM decrypt and Inverse Authentication result.
814 //
815 //*****************************************************************************
816 uint32_t
CRYPTOCcmInvAuthDecryptStatus(void)817 CRYPTOCcmInvAuthDecryptStatus(void)
818 {
819     uint32_t ui32Status;
820 
821     // Get the current DMA status.
822     ui32Status = HWREG(CRYPTO_BASE + CRYPTO_O_DMASTAT);
823 
824     // Check if DMA is still busy.
825     if(ui32Status & CRYPTO_DMA_BSY)
826     {
827         return (AES_DMA_BSY);
828     }
829 
830     // Check the status of the DMA operation - return error if not success.
831     if(ui32Status & CRYPTO_DMA_BUS_ERROR)
832     {
833         return (AES_DMA_BUS_ERROR);
834     }
835 
836     // Operation successful - disable interrupt and return success
837     IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
838     return (AES_SUCCESS);
839 }
840 
841 //*****************************************************************************
842 //
843 // Get the result of the CCM operation.
844 //
845 //*****************************************************************************
846 uint32_t
CRYPTOCcmInvAuthDecryptResultGet(uint32_t ui32AuthLength,uint32_t * pui32CipherText,uint32_t ui32CipherTextLength,uint32_t * pui32CcmTag)847 CRYPTOCcmInvAuthDecryptResultGet(uint32_t ui32AuthLength,
848                                  uint32_t *pui32CipherText,
849                                  uint32_t ui32CipherTextLength,
850                                  uint32_t *pui32CcmTag)
851 {
852     uint32_t volatile ui32Tag[4];
853     uint32_t ui32TagIndex;
854     uint32_t i;
855     uint32_t ui32Idx;
856     uint8_t tempResult = 0;
857 
858     ui32TagIndex = ui32CipherTextLength - ui32AuthLength;
859 
860     // Result has already been copied to the output buffer by DMA
861     // Disable master control.
862     HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = 0x00000000;
863 
864     // Read tag - wait for the context ready bit.
865     do
866     {
867         CPUdelay(1);
868     }
869     while(!(HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) &
870             CRYPTO_AESCTL_SAVED_CONTEXT_RDY));
871 
872     // Read the Tag registers.
873     ui32Tag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0);
874     ui32Tag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1);
875     ui32Tag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2);
876     ui32Tag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3);
877 
878     for(ui32Idx = 0; ui32Idx < ui32AuthLength ; ui32Idx++)
879     {
880         *((uint8_t*)pui32CcmTag + ui32Idx) = *((uint8_t*)ui32Tag + ui32Idx);
881     }
882 
883     // Operation successful -  clear interrupt status.
884     HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = (CRYPTO_IRQCLR_DMA_IN_DONE |
885                                             CRYPTO_IRQCLR_RESULT_AVAIL);
886 
887     /* XOR each byte of the computed tag with the provided tag and OR the results.
888      * If the OR'd result is non-zero, the tags do not match.
889      * There is no branch based on the content of the buffers here to avoid
890      * timing attacks.
891      */
892     for (i = 0; i < ui32AuthLength; i++) {
893         tempResult |= ((uint8_t *) (pui32CipherText))[ui32TagIndex + i] ^ ((uint8_t *)ui32Tag)[i];
894     }
895 
896     return tempResult == 0 ? AES_SUCCESS : CCM_AUTHENTICATION_FAILED;
897 }
898 
899 //*****************************************************************************
900 //
901 // Enable Crypto DMA operation
902 //
903 //*****************************************************************************
904 void
CRYPTODmaEnable(uint32_t ui32Channels)905 CRYPTODmaEnable(uint32_t ui32Channels)
906 {
907     // Check the arguments.
908     ASSERT((ui32Channels & CRYPTO_DMA_CHAN0) |
909            (ui32Channels & CRYPTO_DMA_CHAN1));
910 
911     // Enable the selected channels,
912     if(ui32Channels & CRYPTO_DMA_CHAN0)
913     {
914         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 1;
915     }
916     if(ui32Channels & CRYPTO_DMA_CHAN1)
917     {
918         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 1;
919     }
920 }
921 
922 //*****************************************************************************
923 //
924 // Disable Crypto DMA operation
925 //
926 //*****************************************************************************
927 void
CRYPTODmaDisable(uint32_t ui32Channels)928 CRYPTODmaDisable(uint32_t ui32Channels)
929 {
930     // Check the arguments.
931     ASSERT((ui32Channels & CRYPTO_DMA_CHAN0) |
932            (ui32Channels & CRYPTO_DMA_CHAN1));
933 
934     // Enable the selected channels.
935     if(ui32Channels & CRYPTO_DMA_CHAN0)
936     {
937         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH0CTL, CRYPTO_DMACH0CTL_EN_BITN) = 0;
938     }
939     if(ui32Channels & CRYPTO_DMA_CHAN1)
940     {
941         HWREGBITW(CRYPTO_BASE + CRYPTO_O_DMACH1CTL, CRYPTO_DMACH1CTL_EN_BITN) = 0;
942     }
943 }
944