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