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