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