1 /*
2  * Copyright (c) 2021-2023, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <stdbool.h>
34 #include <stdint.h>
35 #include <string.h>
36 
37 #include <ti/drivers/AESCommon.h>
38 #include <ti/drivers/cryptoutils/aes/AESCommonLPF3.h>
39 #include <ti/drivers/cryptoutils/cryptokey/CryptoKey.h>
40 #include <ti/drivers/cryptoutils/sharedresources/CryptoResourceLPF3.h>
41 #include <ti/drivers/dma/UDMALPF3.h>
42 #include <ti/drivers/Power.h>
43 
44 #include <ti/drivers/dpl/DebugP.h>
45 #include <ti/drivers/dpl/HwiP.h>
46 #include <ti/drivers/dpl/SemaphoreP.h>
47 
48 #include <ti/devices/DeviceFamily.h>
49 #include DeviceFamily_constructPath(driverlib/aes.h)
50 #include DeviceFamily_constructPath(driverlib/udma.h)
51 #include DeviceFamily_constructPath(inc/hw_dma.h)
52 #include DeviceFamily_constructPath(inc/hw_evtsvt.h)
53 #include DeviceFamily_constructPath(inc/hw_ints.h)
54 #include DeviceFamily_constructPath(inc/hw_memmap.h)
55 #include DeviceFamily_constructPath(inc/hw_types.h)
56 
57 /* Static globals */
58 static bool AESCommon_isInitialized = false;
59 
60 /* DMA Control Table Entries */
61 ALLOCATE_CONTROL_TABLE_ENTRY(dmaChannel4ControlTableEntry, DMA_CH4);
62 ALLOCATE_CONTROL_TABLE_ENTRY(dmaChannel5ControlTableEntry, DMA_CH5);
63 
64 static volatile uDMAControlTableEntry *dmaPriControlTableEntryChA = &dmaChannel4ControlTableEntry;
65 static volatile uDMAControlTableEntry *dmaPriControlTableEntryChB = &dmaChannel5ControlTableEntry;
66 
67 /* Forward declarations */
68 void AESCommonLPF3_setPowerConstraint(AESCommonLPF3_Object *object);
69 void AESCommonLPF3_releasePowerConstraint(AESCommonLPF3_Object *object);
70 
71 /*
72  *  ======== AESCommonLPF3_init ========
73  */
AESCommonLPF3_init(void)74 void AESCommonLPF3_init(void)
75 {
76     CryptoResourceLPF3_constructRTOSObjects();
77 
78     UDMALPF3_init();
79 
80     AESCommon_isInitialized = true;
81 }
82 
83 /*
84  *  ======== AESCommonLPF3_construct ========
85  */
AESCommonLPF3_construct(AESCommonLPF3_Object * object,AES_ReturnBehavior returnBehavior,uint32_t timeout)86 int_fast16_t AESCommonLPF3_construct(AESCommonLPF3_Object *object, AES_ReturnBehavior returnBehavior, uint32_t timeout)
87 {
88     DebugP_assert(object);
89 
90     uintptr_t interruptKey = HwiP_disable();
91 
92     if (!AESCommon_isInitialized || object->isOpen)
93     {
94         HwiP_restore(interruptKey);
95 
96         return AES_STATUS_ERROR;
97     }
98 
99     object->isOpen = true;
100 
101     HwiP_restore(interruptKey);
102 
103     object->returnBehavior = returnBehavior;
104 
105     if (returnBehavior == AES_RETURN_BEHAVIOR_BLOCKING)
106     {
107         object->semaphoreTimeout = timeout;
108     }
109     else
110     {
111         object->semaphoreTimeout = SemaphoreP_NO_WAIT;
112     }
113 
114     if (returnBehavior != AES_RETURN_BEHAVIOR_POLLING)
115     {
116         /*
117          * Configure DMA channels 4 & 5 for LAES TRG A & B respectively.
118          * Channels 4 & 5 are the only channels which can be used with LAES
119          * because channels 6 & 7 do not support the DMA Done signal.
120          *
121          * AES Channel A is used for input and Channel B is used for output.
122          *
123          * CMAC and CBC-MAC AES modes use input DMA only.
124          */
125         HWREG(EVTSVT_BASE + EVTSVT_O_DMACH4SEL) = EVTSVT_DMACH4SEL_IPID_LAESTRGA;
126         HWREG(EVTSVT_BASE + EVTSVT_O_DMACH5SEL) = EVTSVT_DMACH5SEL_IPID_LAESTRGB;
127     }
128 
129     object->cryptoResourceLocked = false;
130     object->operationInProgress  = false;
131     object->powerConstraintSet   = false;
132 
133     /* Set power dependency. Power up and enable clock for DMA peripheral */
134     Power_setDependency(PowerLPF3_PERIPH_DMA);
135 
136     /* Set power dependency. Power up and enable clock for LAES peripheral */
137     Power_setDependency(PowerLPF3_PERIPH_AES);
138 
139     return AES_STATUS_SUCCESS;
140 }
141 
142 /*
143  *  ======== AESCommonLPF3_close ========
144  */
AESCommonLPF3_close(AESCommonLPF3_Object * object)145 void AESCommonLPF3_close(AESCommonLPF3_Object *object)
146 {
147     DebugP_assert(object);
148 
149     /* Mark the module as available */
150     object->isOpen = false;
151 
152     /* Release power dependency on DMA module */
153     Power_releaseDependency(PowerLPF3_PERIPH_DMA);
154 
155     /* Release power dependency on LAES module */
156     Power_releaseDependency(PowerLPF3_PERIPH_AES);
157 }
158 
159 /*
160  *  ======== AESCommonLPF3_setOperationInProgress ========
161  */
AESCommonLPF3_setOperationInProgress(AESCommonLPF3_Object * object)162 int_fast16_t AESCommonLPF3_setOperationInProgress(AESCommonLPF3_Object *object)
163 {
164     uintptr_t interruptKey = HwiP_disable();
165 
166     if (object->operationInProgress)
167     {
168         HwiP_restore(interruptKey);
169 
170         return AES_STATUS_ERROR;
171     }
172 
173     object->operationInProgress = true;
174 
175     HwiP_restore(interruptKey);
176 
177     return AES_STATUS_SUCCESS;
178 }
179 
180 /*
181  *  ======== AESCommonLPF3_setupOperation ========
182  */
AESCommonLPF3_setupOperation(CryptoKey * key,uint32_t autoCfgVal)183 void AESCommonLPF3_setupOperation(CryptoKey *key, uint32_t autoCfgVal)
184 {
185     /* Load Key */
186     AESCommonLPF3_loadKey(key);
187 
188     /* Set AUTOCFG */
189     AESSetAUTOCFG(autoCfgVal);
190 }
191 
192 /*
193  *  ======== AESCommonLPF3_loadKey ========
194  */
AESCommonLPF3_loadKey(const CryptoKey * key)195 void AESCommonLPF3_loadKey(const CryptoKey *key)
196 {
197     const uint8_t *keyMaterial;
198 
199     /* Only plaintext CryptoKeys are supported currently */
200     DebugP_assert((key->encoding == CryptoKey_PLAINTEXT) || (key->encoding == CryptoKey_BLANK_PLAINTEXT));
201 
202     keyMaterial = key->u.plaintext.keyMaterial;
203 
204     DebugP_assert(keyMaterial);
205 
206     /* AES engine supports only 128-bit (16-byte) keys. */
207     DebugP_assert(key->u.plaintext.keyLength == AES_128_KEY_LENGTH_BYTES);
208 
209     /* Write keyMaterial to the AES engine */
210     AESWriteKEY(keyMaterial);
211 }
212 /*
213  *  ======== AESAESCommonLPF3_cleanup ========
214  */
AESCommonLPF3_cleanup(AESCommonLPF3_Object * object)215 void AESCommonLPF3_cleanup(AESCommonLPF3_Object *object)
216 {
217     if (object->returnBehavior != AES_RETURN_BEHAVIOR_POLLING)
218     {
219         AESSetIMASK((uint32_t)0U);
220         AESDisableDMA();
221 
222         IntDisable(INT_AES_COMB);
223 
224         /*
225          * Disable DMA channels A & B.  Assuming DMA channels are statically
226          * mapped, this should always be safe to do. This must be done before
227          * calling AESAbort.
228          */
229         UDMALPF3_channelDisable(AESCommonLPF3_DMA_CHA_BITMASK | AESCommonLPF3_DMA_CHB_BITMASK);
230     }
231 
232     /*
233      * Abort any spurious encryption and clear TXT, BUF, DMA, AUTOCFG registers.
234      */
235     AESAbort();
236 
237     /* Clear all AES interrupts */
238     AESClearInterrupt(AES_ICLR_ALL);
239 
240     if (object->cryptoResourceLocked)
241     {
242         object->cryptoResourceLocked = false;
243         /*
244          * Grant access for other threads to use the crypto module.
245          * The semaphore must be posted before the callbackFxn to allow
246          * the chaining of operations.
247          */
248         CryptoResourceLPF3_releaseLock();
249     }
250 
251     AESCommonLPF3_releasePowerConstraint(object);
252 }
253 
254 /*
255  *  ======== AESCommonLPF3_setupSegmentedOperation ========
256  */
AESCommonLPF3_setupSegmentedOperation(AESCommonLPF3_Object * object,const CryptoKey * key)257 int_fast16_t AESCommonLPF3_setupSegmentedOperation(AESCommonLPF3_Object *object, const CryptoKey *key)
258 {
259     int_fast16_t status;
260 
261     /* Check that there is no operation in progress for this driver instance */
262     status = AESCommonLPF3_setOperationInProgress(object);
263 
264     if (status == AES_STATUS_SUCCESS)
265     {
266         /* Make internal copy of crypto key */
267         object->key = *key;
268 
269         /* returnStatus is only changed in the case of an error or cancellation */
270         object->returnStatus = AES_STATUS_SUCCESS;
271     }
272 
273     return status;
274 }
275 
276 /*
277  *  ======== AESCommonLPF3_configInputDMA ========
278  */
AESCommonLPF3_configInputDMA(const void * input,size_t inputLength)279 void AESCommonLPF3_configInputDMA(const void *input, size_t inputLength)
280 {
281     uint32_t control;
282     uint32_t numTransfers;
283 
284     /*
285      * Set the source data width and address increment based upon the address
286      * alignment. Arbitrate after 16-bytes (AES block size). No destination
287      * address increment.
288      */
289 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 1)
290     if (((uintptr_t)input & 0x1U) != 0U)
291     {
292         control      = UDMA_DST_INC_NONE | UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_ARB_16;
293         numTransfers = (uint32_t)inputLength;
294     }
295     else if (((uintptr_t)input & 0x2U) != 0U)
296     {
297         control      = UDMA_DST_INC_NONE | UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_ARB_8;
298         numTransfers = (uint32_t)inputLength >> 1;
299     }
300     else
301 #endif
302     {
303         control      = UDMA_DST_INC_NONE | UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_ARB_4;
304         numTransfers = (uint32_t)inputLength >> 2;
305     }
306 
307     /*
308      * Setup DMA channel A Primary Control Struct:
309      *  -
310      */
311     uDMASetChannelControl(dmaPriControlTableEntryChA, control);
312 
313     /*
314      * Setup DMA channel A Primary Control Struct:
315      *  - Mode = Basic
316      *  - Input & Output end pointers
317      *  - Set n-1, where n = number DMA transfers that the DMA cycle contains.
318      */
319     uDMASetChannelTransfer(dmaPriControlTableEntryChA,
320                            UDMA_MODE_BASIC,
321                            (void *)input,
322                            (void *)(AES_BASE + AES_O_DMACHA),
323                            numTransfers);
324 
325     /* Enable the channel for AES input */
326     UDMALPF3_channelEnable(AESCommonLPF3_DMA_CHA_BITMASK);
327 }
328 
329 /*
330  *  ======== AESCommonLPF3_isDMALengthValid ========
331  */
AESCommonLPF3_isDMALengthValid(const void * input,const void * output,size_t length)332 bool AESCommonLPF3_isDMALengthValid(const void *input, const void *output, size_t length)
333 {
334     size_t maxLength = 4096;
335 
336 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 1)
337     uintptr_t alignment = (uintptr_t)input | (uintptr_t)output;
338 
339     if (alignment & 0x1U)
340     {
341         maxLength = 1024;
342     }
343     else if (alignment & 0x2U)
344     {
345         maxLength = 2048;
346     }
347 #endif
348     return (length <= maxLength);
349 }
350 
351 /*
352  *  ======== AESCommonLPF3_configOutputDMA ========
353  */
AESCommonLPF3_configOutputDMA(void * output,size_t outputLength)354 void AESCommonLPF3_configOutputDMA(void *output, size_t outputLength)
355 {
356     uint32_t control;
357     uint32_t numTransfers;
358 
359     /*
360      * Set the source data width and address increment based upon the address
361      * alignment. Arbitrate after 16-bytes (AES block size). No source address
362      * increment.
363      */
364 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 1)
365     if (((uintptr_t)output & 0x1U) != 0U)
366     {
367         control      = UDMA_SRC_INC_NONE | UDMA_SIZE_8 | UDMA_DST_INC_8 | UDMA_ARB_16;
368         numTransfers = outputLength;
369     }
370     else if (((uintptr_t)output & 0x2U) != 0U)
371     {
372         control      = UDMA_SRC_INC_NONE | UDMA_SIZE_16 | UDMA_DST_INC_16 | UDMA_ARB_8;
373         numTransfers = outputLength >> 1;
374     }
375     else
376 #endif
377     {
378         control      = UDMA_SRC_INC_NONE | UDMA_SIZE_32 | UDMA_DST_INC_32 | UDMA_ARB_4;
379         numTransfers = outputLength >> 2;
380     }
381 
382     /*
383      * Setup DMA channel B Primary Control struct control params:
384      *  -
385      */
386     uDMASetChannelControl(dmaPriControlTableEntryChB, control);
387 
388     /*
389      * Setup DMA channel B Primary Control struct transfer params:
390      *  - Mode = Basic
391      *  - Input & Output end pointers
392      *  - Set n-1, where n = number DMA transfers that the DMA cycle contains.
393      */
394     uDMASetChannelTransfer(dmaPriControlTableEntryChB,
395                            UDMA_MODE_BASIC,
396                            (void *)(AES_BASE + AES_O_DMACHB),
397                            output,
398                            numTransfers);
399 
400     /* Enable the channel for AES input */
401     UDMALPF3_channelEnable(AESCommonLPF3_DMA_CHB_BITMASK);
402 }
403 
404 /*
405  *  ======== AESCommonLPF3_cancelDMA ========
406  */
AESCommonLPF3_cancelDMA(bool cancelChannelB)407 void AESCommonLPF3_cancelDMA(bool cancelChannelB)
408 {
409     IntDisable(INT_AES_COMB);
410     AESSetIMASK((uint32_t)0U);
411     AESDisableDMA();
412 
413     uint32_t channelBitMask = AESCommonLPF3_DMA_CHA_BITMASK;
414     if (cancelChannelB)
415     {
416         channelBitMask |= AESCommonLPF3_DMA_CHB_BITMASK;
417     }
418 
419     /* Disable DMA channel(s) */
420     UDMALPF3_channelDisable(channelBitMask);
421 
422     /* Set DMA channels to STOP */
423     uDMASetChannelTransfer(dmaPriControlTableEntryChA, UDMA_MODE_STOP, 0, 0, 0);
424 
425     if (cancelChannelB)
426     {
427         uDMASetChannelTransfer(dmaPriControlTableEntryChB, UDMA_MODE_STOP, 0, 0, 0);
428     }
429 
430     /* Abort must be done after disabling DMA channels according to LAES spec */
431     AESAbort();
432 
433     /* Clear all AES interrupts */
434     AESClearInterrupt(AES_ICLR_ALL);
435 }
436 
437 /*
438  *  ======== AESCommonLPF3_cancelOperation ========
439  */
AESCommonLPF3_cancelOperation(AESCommonLPF3_Object * object,bool cancelDMAChannelB)440 void AESCommonLPF3_cancelOperation(AESCommonLPF3_Object *object, bool cancelDMAChannelB)
441 {
442     if (object->returnBehavior != AES_RETURN_BEHAVIOR_POLLING)
443     {
444         AESCommonLPF3_cancelDMA(cancelDMAChannelB);
445     }
446 
447     AESCommonLPF3_releasePowerConstraint(object);
448 
449     object->returnStatus = AES_STATUS_CANCELED;
450 
451     AESCommonLPF3_clearOperationInProgress(object);
452 
453     if (object->cryptoResourceLocked)
454     {
455         object->cryptoResourceLocked = false;
456         /*
457          * Grant access for other threads to use the crypto module.
458          * The semaphore must be posted before the callbackFxn to allow
459          * the chaining of operations.
460          */
461         CryptoResourceLPF3_releaseLock();
462     }
463 }
464 
465 /*
466  *  ======== AESCommonLPF3_setupHwi ========
467  */
AESCommonLPF3_setupHwi(HwiP_Fxn hwiFxn,uintptr_t hwiFxnArg,uint8_t intPriority)468 void AESCommonLPF3_setupHwi(HwiP_Fxn hwiFxn, uintptr_t hwiFxnArg, uint8_t intPriority)
469 {
470     HwiP_setFunc(&CryptoResourceLPF3_hwi, hwiFxn, hwiFxnArg);
471     HwiP_setPriority(INT_AES_COMB, (uint32_t)intPriority);
472     IntEnable((uint32_t)INT_AES_COMB);
473 }
474 
475 /*
476  *  ======== AESCommonLPF3_setPowerConstraint ========
477  */
AESCommonLPF3_setPowerConstraint(AESCommonLPF3_Object * object)478 void AESCommonLPF3_setPowerConstraint(AESCommonLPF3_Object *object)
479 {
480     /* Ignore return value since it always returns Power_SOK */
481     (void)Power_setConstraint(PowerLPF3_DISALLOW_STANDBY);
482     object->powerConstraintSet = true;
483 }
484 
485 /*
486  *  ======== AESCommonLPF3_releasePowerConstraint ========
487  */
AESCommonLPF3_releasePowerConstraint(AESCommonLPF3_Object * object)488 void AESCommonLPF3_releasePowerConstraint(AESCommonLPF3_Object *object)
489 {
490     if (object->powerConstraintSet)
491     {
492         object->powerConstraintSet = false;
493         /* Ignore return value since it always returns Power_SOK */
494         (void)Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
495     }
496 }
497 
498 /*
499  *  ======== AESCommonLPF3_setupDMA ========
500  */
AESCommonLPF3_setupDMA(AESCommonLPF3_Object * object,uint32_t dmaConfig)501 void AESCommonLPF3_setupDMA(AESCommonLPF3_Object *object, uint32_t dmaConfig)
502 {
503     AESSetupDMA(dmaConfig);
504 
505     AESCommonLPF3_setPowerConstraint(object);
506 }
507 
508 /*
509  *  ======== AESCommonLPF3_cleanupHwi ========
510  */
AESCommonLPF3_cleanupHwi(AESCommonLPF3_Object * object)511 void AESCommonLPF3_cleanupHwi(AESCommonLPF3_Object *object)
512 {
513     AESDisableDMA();
514     AESSetIMASK((uint32_t)0U);
515     /* Clear all AES interrupts */
516     AESClearInterrupt(AES_ICLR_ALL);
517 
518     AESCommonLPF3_releasePowerConstraint(object);
519 }
520