1 /*
2 * Copyright (c) 2021-2024, 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/aesecb/AESECBLPF3.h>
38 #include <ti/drivers/AESCommon.h>
39 #include <ti/drivers/AESECB.h>
40 #include <ti/drivers/cryptoutils/aes/AESCommonLPF3.h>
41 #include <ti/drivers/cryptoutils/cryptokey/CryptoKey.h>
42 #include <ti/drivers/cryptoutils/sharedresources/CryptoResourceLPF3.h>
43 #include <ti/drivers/dma/UDMALPF3.h>
44
45 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
46 #include <ti/drivers/cryptoutils/hsm/HSMLPF3.h>
47 #endif
48
49 #include <ti/drivers/dpl/DebugP.h>
50 #include <ti/drivers/dpl/HwiP.h>
51 #include <ti/drivers/dpl/SemaphoreP.h>
52
53 #include <ti/devices/DeviceFamily.h>
54 #include DeviceFamily_constructPath(driverlib/aes.h)
55 #include DeviceFamily_constructPath(inc/hw_aes.h)
56 #include DeviceFamily_constructPath(inc/hw_ints.h)
57
58 /*
59 * Default AES ECB auto config:
60 * ECB SRC as BUF
61 * Trigger points for auto ECB as RDTX3 and WRBUF3S
62 * (the first encryption starts by writing BUF3, the successive ones by reading TXT3)
63 * BUSHALT enabled
64 */
65 #if DeviceFamily_PARENT == DeviceFamily_PARENT_CC23X0
66 #define AESECBLPF3_DEFAULT_AUTOCFG \
67 ((uint32_t)AES_AUTOCFG_AESSRC_BUF | (uint32_t)AES_AUTOCFG_TRGAES_WRBUF3S | \
68 (uint32_t)AES_AUTOCFG_TRGAES_RDTXT3 | (uint32_t)AES_AUTOCFG_BUSHALT_EN)
69 #elif DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX
70 #define AESECBLPF3_DEFAULT_AUTOCFG \
71 ((uint32_t)AES_AUTOCFG_ECBSRC_BUF | (uint32_t)AES_AUTOCFG_TRGECB_WRBUF3S | \
72 (uint32_t)AES_AUTOCFG_TRGECB_RDTXT3 | (uint32_t)AES_AUTOCFG_BUSHALT_EN)
73 #else
74 #error "Unsupported DeviceFamily_Parent for AESECBLPF3!"
75 #endif
76
77 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
78 #define PSA_SYM_MODE_GCM_NONE 0U
79
80 /* Size of state asset for GCM/CCM continuation */
81 #define PSA_SYM_STATE_ASSET_SIZE 48U
82 #endif
83
84 /*
85 * AES ECB DMA config:
86 * - ADRCHA = BUF0
87 * - TRGCHA = ECBSTART
88 * - ADRCHB = TXT0
89 * - TRGCHB = ECBDONE
90 * - DONEACT = GATE_TRGECB_ON_CHA_DEL (to avoid spurious last ECB using DMA
91 * if data length > 1 block)
92 */
93 #if DeviceFamily_PARENT == DeviceFamily_PARENT_CC23X0
94 #define AESECBLPF3_DMA_CONFIG \
95 ((uint32_t)AES_DMA_ADRCHA_BUF0 | (uint32_t)AES_DMA_TRGCHA_AESSTART | \
96 (uint32_t)AES_DMA_DONEACT_GATE_TRGAES_ON_CHA_DEL | (uint32_t)AES_DMA_ADRCHB_TXT0 | \
97 (uint32_t)AES_DMA_TRGCHB_AESDONE)
98 #elif DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX
99 #define AESECBLPF3_DMA_CONFIG \
100 ((uint32_t)AES_DMA_ADRCHA_BUF0 | (uint32_t)AES_DMA_TRGCHA_ECBSTART | \
101 (uint32_t)AES_DMA_DONEACT_GATE_TRGECB_ON_CHA_DEL | (uint32_t)AES_DMA_ADRCHB_TXT0 | \
102 (uint32_t)AES_DMA_TRGCHB_ECBDONE)
103 #else
104 #error "Unsupported DeviceFamily_Parent for AESECBLPF3!"
105 #endif
106
107 /* Forward declarations */
108 static int_fast16_t AESECBLPF3_checkOperation(const AESECBLPF3_Object *object, const AESECB_Operation *operation);
109 static inline void AESECBLPF3_processDataCPU(const uint8_t *input, uint8_t *output, size_t inputLength);
110 static inline void AESECBLPF3_processDataDMA(AESCommonLPF3_Object *object,
111 const uint8_t *input,
112 uint8_t *output,
113 size_t inputLength);
114 static inline int_fast16_t AESECBLPF3_oneStepOperation(AESECB_Handle handle,
115 AESECB_Operation *operation,
116 AESECB_OperationType operationType);
117 static int_fast16_t AESECBLPF3_startOperation(AESECB_Handle handle, AESECB_Operation *operation);
118 static inline int_fast16_t AESECBLPF3_waitForResult(AESECB_Handle handle);
119
120 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
121 static int_fast16_t AESECBLPF3HSM_oneStepOperation(AESECB_Handle handle,
122 AESECB_Operation *operation,
123 AESECB_OperationType operationType);
124 static int_fast16_t AESECBLPF3HSM_processOneStep(AESECB_Handle handle);
125
126 static int_fast16_t AESECBLPF3HSM_addData(AESECB_Handle handle, AESECB_Operation *operation);
127
128 static int_fast16_t AESECBLPF3HSM_finalize(AESECB_Handle handle, AESECB_Operation *operation);
129
130 #endif
131
132 /*
133 * ======== AESEBCLPF3_getObject ========
134 */
AESEBCLPF3_getObject(AESECB_Handle handle)135 static inline AESECBLPF3_Object *AESEBCLPF3_getObject(AESECB_Handle handle)
136 {
137 AESECBLPF3_Object *object = (AESECBLPF3_Object *)handle->object;
138 DebugP_assert(object);
139
140 return object;
141 }
142
143 /*
144 * ======== AESECBLPF3_hwiFxn ========
145 */
AESECBLPF3_hwiFxn(uintptr_t arg0)146 static void AESECBLPF3_hwiFxn(uintptr_t arg0)
147 {
148 AESECB_Handle handle = (AESECB_Handle)arg0;
149 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
150
151 /*
152 * Only the output channel B interrupt is enabled.
153 */
154 uint32_t intStatus = AESGetMaskedInterruptStatus();
155
156 /* Disable DMA, clear interupts, and release power constraint */
157 AESCommonLPF3_cleanupHwi(&object->common);
158
159 if ((intStatus & (uint32_t)AES_MIS_CHBDONE_M) != (uint32_t)0U)
160 {
161 UDMALPF3_clearInterrupt(AESCommonLPF3_DMA_CHB_BITMASK);
162
163 if ((object->operationType == AESECB_OPERATION_TYPE_ENCRYPT) ||
164 (object->operationType == AESECB_OPERATION_TYPE_FINALIZE_ENCRYPT_SEGMENTED))
165 {
166 AESCommonLPF3_clearOperationInProgress(&object->common);
167 }
168
169 /* Cleanup and release crypto resource lock */
170 AESCommonLPF3_cleanup(&object->common);
171
172 if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_BLOCKING)
173 {
174 /* Unblock the pending task to signal that the operation is complete */
175 SemaphoreP_post(&CryptoResourceLPF3_operationSemaphore);
176 }
177 else
178 {
179 /* Call the callback function provided by the application */
180 object->callbackFxn(handle, object->common.returnStatus, object->operation, object->operationType);
181 }
182 }
183 }
184
185 /*
186 * ======== AESECB_init ========
187 */
AESECB_init(void)188 void AESECB_init(void)
189 {
190 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
191 HSMLPF3_constructRTOSObjects();
192 #endif
193 AESCommonLPF3_init();
194 }
195
196 /*
197 * ======== AESECB_construct ========
198 */
AESECB_construct(AESECB_Config * config,const AESECB_Params * params)199 AESECB_Handle AESECB_construct(AESECB_Config *config, const AESECB_Params *params)
200 {
201 DebugP_assert(config);
202
203 int_fast16_t status;
204 AESECB_Handle handle = config;
205 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
206
207 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
208 /* Initialize and boot HSM */
209 if (HSMLPF3_init() != HSMLPF3_STATUS_SUCCESS)
210 {
211 /* Upon HSM Boot failure, the AES-CCM Driver stores the failure status in the object
212 * This is done so that users of the AES-CCM Driver do not get a NULL handle and still can use
213 * the driver in LAES mode.
214 */
215 object->hsmStatus = HSMLPF3_STATUS_ERROR;
216 }
217 else
218 {
219 object->hsmStatus = HSMLPF3_STATUS_SUCCESS;
220 }
221
222 object->segmentedOperationInProgress = false;
223 #endif
224
225 /* If params are NULL, use defaults */
226 if (params == NULL)
227 {
228 params = &AESECB_defaultParams;
229 }
230
231 DebugP_assert((params->returnBehavior != AESECB_RETURN_BEHAVIOR_CALLBACK) || (params->callbackFxn != NULL));
232
233 object->callbackFxn = params->callbackFxn;
234 object->threadSafe = true;
235
236 status = AESCommonLPF3_construct(&object->common, (AES_ReturnBehavior)params->returnBehavior, params->timeout);
237
238 if (status != AES_STATUS_SUCCESS)
239 {
240 return NULL;
241 }
242
243 return handle;
244 }
245
246 /*
247 * ======== AESECB_close ========
248 */
AESECB_close(AESECB_Handle handle)249 void AESECB_close(AESECB_Handle handle)
250 {
251 DebugP_assert(handle);
252
253 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
254
255 AESCommonLPF3_close(&object->common);
256 }
257
258 /*
259 * ======== AESECB_oneStepEncrypt ========
260 */
AESECB_oneStepEncrypt(AESECB_Handle handle,AESECB_Operation * operation)261 int_fast16_t AESECB_oneStepEncrypt(AESECB_Handle handle, AESECB_Operation *operation)
262 {
263 int_fast16_t status = AESECB_STATUS_SUCCESS;
264
265 if (operation->key->encoding == CryptoKey_PLAINTEXT || operation->key->encoding == CryptoKey_KEYSTORE)
266 {
267 status = AESECBLPF3_oneStepOperation(handle, operation, AESECB_OPERATION_TYPE_ENCRYPT);
268 }
269 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
270 else if (operation->key->encoding == CryptoKey_PLAINTEXT_HSM)
271 {
272 status = AESECBLPF3HSM_oneStepOperation(handle, operation, AESECB_OPERATION_TYPE_ENCRYPT);
273 }
274 #endif
275 else
276 {
277 status = AESECB_STATUS_ERROR;
278 }
279 return status;
280 }
281
282 /*
283 * ======== AESECB_oneStepDecrypt ========
284 */
AESECB_oneStepDecrypt(AESECB_Handle handle,AESECB_Operation * operation)285 int_fast16_t AESECB_oneStepDecrypt(AESECB_Handle handle, AESECB_Operation *operation)
286 {
287 DebugP_assert(handle);
288 DebugP_assert(operation);
289
290 int_fast16_t status = AESECB_STATUS_SUCCESS;
291
292 if (operation->key->encoding == CryptoKey_PLAINTEXT || operation->key->encoding == CryptoKey_KEYSTORE)
293 {
294 status = AESECB_STATUS_FEATURE_NOT_SUPPORTED;
295 }
296 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
297 else if (operation->key->encoding == CryptoKey_PLAINTEXT_HSM)
298 {
299 status = AESECBLPF3HSM_oneStepOperation(handle, operation, AESECB_OPERATION_TYPE_DECRYPT);
300 }
301 #endif
302 else
303 {
304 status = AESECB_STATUS_ERROR;
305 }
306
307 return status;
308 }
309
310 /*
311 * ======== AESECBLPF3_checkOperation ========
312 */
AESECBLPF3_checkOperation(const AESECBLPF3_Object * object,const AESECB_Operation * operation)313 static int_fast16_t AESECBLPF3_checkOperation(const AESECBLPF3_Object *object, const AESECB_Operation *operation)
314 {
315 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 0)
316 /* Check word-alignment of input & output pointers */
317 if (!IS_WORD_ALIGNED(operation->input) || !IS_WORD_ALIGNED(operation->output))
318 {
319 return AESECB_STATUS_UNALIGNED_IO_NOT_SUPPORTED;
320 }
321 #endif
322
323 /* Verify input length is a non-zero multiple of the AES block size */
324 if ((operation->inputLength == 0UL) || (AES_NON_BLOCK_SIZE_MULTIPLE_LENGTH(operation->inputLength) > 0UL))
325 {
326 return AESECB_STATUS_ERROR;
327 }
328
329 /* Check DMA xfer limit for blocking and callback modes */
330 if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) &&
331 !AESCommonLPF3_isDMALengthValid(operation->input, operation->output, operation->inputLength))
332 {
333 return AESECB_STATUS_ERROR;
334 }
335
336 return AESECB_STATUS_SUCCESS;
337 }
338
339 /*
340 * ======== AESECBLPF3_oneStepOperation ========
341 */
AESECBLPF3_oneStepOperation(AESECB_Handle handle,AESECB_Operation * operation,AESECB_OperationType operationType)342 static inline int_fast16_t AESECBLPF3_oneStepOperation(AESECB_Handle handle,
343 AESECB_Operation *operation,
344 AESECB_OperationType operationType)
345 {
346 DebugP_assert(handle);
347 DebugP_assert(operation);
348
349 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
350 int_fast16_t status;
351
352 status = AESECBLPF3_checkOperation(object, operation);
353
354 if (status != AESECB_STATUS_SUCCESS)
355 {
356 return status;
357 }
358
359 /*
360 * Check that there are no operations already in progress.
361 * If not, mark the current operation to be in progress
362 */
363 status = AESCommonLPF3_setOperationInProgress(&object->common);
364
365 if (status != AESECB_STATUS_SUCCESS)
366 {
367 return status;
368 }
369
370 if (object->threadSafe)
371 {
372 if (!CryptoResourceLPF3_acquireLock(object->common.semaphoreTimeout))
373 {
374 AESCommonLPF3_clearOperationInProgress(&object->common);
375 return AESECB_STATUS_RESOURCE_UNAVAILABLE;
376 }
377
378 object->common.cryptoResourceLocked = true;
379 }
380
381 object->operation = operation;
382 object->operationType = operationType;
383
384 object->common.key = *(operation->key);
385 /* We will only change the returnStatus if there is an error or cancellation */
386 object->common.returnStatus = AESECB_STATUS_SUCCESS;
387
388 return AESECBLPF3_startOperation(handle, operation);
389 }
390
391 /*
392 * ======== AESECBLPF3_startOperation ========
393 */
AESECBLPF3_startOperation(AESECB_Handle handle,AESECB_Operation * operation)394 static int_fast16_t AESECBLPF3_startOperation(AESECB_Handle handle, AESECB_Operation *operation)
395 {
396 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
397 int_fast16_t status;
398
399 /* Set up the key and AES engine to begin an operation */
400 if (operation->inputLength == AES_BLOCK_SIZE)
401 {
402 AESCommonLPF3_setupOperation(&object->common.key, AESEBCLPF3_SINGLE_BLOCK_AUTOCFG);
403 }
404 else
405 {
406 AESCommonLPF3_setupOperation(&object->common.key, AESECBLPF3_DEFAULT_AUTOCFG);
407 }
408
409 if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) &&
410 (operation->inputLength >= AESECBLPF3_DMA_SIZE_THRESHOLD))
411 {
412 /*
413 * We need to set the HWI function and priority since the same physical
414 * interrupt is shared by multiple drivers and they all need to coexist.
415 * Whenever a driver starts an operation, it registers its HWI callback
416 * with the OS.
417 */
418 AESECBLPF3_HWAttrs const *hwAttrs = handle->hwAttrs;
419 AESCommonLPF3_setupHwi(AESECBLPF3_hwiFxn, (uintptr_t)handle, hwAttrs->intPriority);
420 }
421
422 AESECBLPF3_processData(&object->common, operation->input, operation->output, operation->inputLength);
423
424 status = AESECBLPF3_waitForResult(handle);
425
426 return status;
427 }
428
429 /*
430 * ======== AESECBLPF3_processData ========
431 */
AESECBLPF3_processData(AESCommonLPF3_Object * object,const uint8_t * input,uint8_t * output,size_t inputLength)432 void AESECBLPF3_processData(AESCommonLPF3_Object *object, const uint8_t *input, uint8_t *output, size_t inputLength)
433 {
434 /*
435 * Process all operations with data length less than the DMA size
436 * threshold as a polling mode operation.
437 */
438 if ((object->returnBehavior == AES_RETURN_BEHAVIOR_POLLING) || (inputLength < AESECBLPF3_DMA_SIZE_THRESHOLD))
439 {
440 /* Process all blocks with CPU R/W */
441 AESECBLPF3_processDataCPU(input, output, inputLength);
442 }
443 else
444 {
445 AESECBLPF3_processDataDMA(object, input, output, inputLength);
446 }
447 }
448
449 /*
450 * ======== AESECBLPF3_processDataCPU ========
451 */
AESECBLPF3_processDataCPU(const uint8_t * input,uint8_t * output,size_t inputLength)452 static inline void AESECBLPF3_processDataCPU(const uint8_t *input, uint8_t *output, size_t inputLength)
453 {
454 /*
455 * For efficiency, the next block of data can be written to AES BUF regs
456 * while the AES engine is encrypting the previous block. The AES engine
457 * takes 23-cycles to encrypt a block. If the SW can load blocks faster
458 * than that, SW must wait until the AES HW is idle after writing two
459 * blocks consecutively to avoid overwriting data before the AES engine
460 * can consume it.
461 */
462 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 1)
463 size_t inputBytesProcessed = 0;
464 size_t outputBytesProcessed = 0;
465
466 if (!IS_WORD_ALIGNED(input) || !IS_WORD_ALIGNED(output))
467 {
468 /* Write first block of input to trigger encryption */
469 AESWriteBUF(&input[inputBytesProcessed]);
470 inputBytesProcessed += AES_BLOCK_SIZE;
471
472 while (inputBytesProcessed < inputLength)
473 {
474 /* Preload next input block */
475 AESWriteBUF(&input[inputBytesProcessed]);
476 inputBytesProcessed += AES_BLOCK_SIZE;
477
478 #ifdef AES_BUSHALT_DISABLED
479 /* Wait for encryption of previous input to complete */
480 while (AESGetStatus() != (uint32_t)AES_STA_STATE_IDLE) {}
481 #endif
482 /*
483 * Read output and trigger encryption of next input that was
484 * preloaded at the start of this loop.
485 */
486 AESReadTXT(&output[outputBytesProcessed]);
487 outputBytesProcessed += AES_BLOCK_SIZE;
488 }
489
490 /* Avoid triggering a spurious encryption upon reading the final output */
491 AESClearAUTOCFGTrigger();
492 #ifdef AES_BUSHALT_DISABLED
493 /* Wait for encryption of final input block */
494 while (AESGetStatus() != (uint32_t)AES_STA_STATE_IDLE) {}
495 #endif
496 /* Read final output */
497 AESReadTXT(&output[outputBytesProcessed]);
498 }
499 else
500 #endif /* (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 1) */
501 {
502 AESProcessAlignedBlocksECB((const uint32_t *)input,
503 (uint32_t *)output,
504 (uint32_t)AES_GET_NUM_BLOCKS(inputLength));
505 }
506 }
507
508 /*
509 * ======== AESECBLPF3_processDataDMA ========
510 */
AESECBLPF3_processDataDMA(AESCommonLPF3_Object * object,const uint8_t * input,uint8_t * output,size_t inputLength)511 static inline void AESECBLPF3_processDataDMA(AESCommonLPF3_Object *object,
512 const uint8_t *input,
513 uint8_t *output,
514 size_t inputLength)
515 {
516 /* Clear BUSHALT when using DMA */
517 AESClearAUTOCFGBusHalt();
518
519 /* Setup DMA configuration and set power constraint */
520 AESCommonLPF3_setupDMA(object, AESECBLPF3_DMA_CONFIG);
521
522 AESCommonLPF3_configInputDMA(input, inputLength);
523 AESCommonLPF3_configOutputDMA(output, inputLength);
524
525 /* Enable interrupt upon output DMA done */
526 AESSetIMASK((uint32_t)AES_IMASK_CHBDONE_M);
527
528 /* Manually trigger the DMA to start the ECB operation */
529 AESSetTrigger((uint32_t)AES_TRG_DMACHA);
530 }
531
532 /*
533 * ======== AESECBLPF3_waitForResult ========
534 */
AESECBLPF3_waitForResult(AESECB_Handle handle)535 static inline int_fast16_t AESECBLPF3_waitForResult(AESECB_Handle handle)
536 {
537 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
538 int_fast16_t status;
539
540 if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_POLLING) ||
541 (object->operation->inputLength < AESECBLPF3_DMA_SIZE_THRESHOLD))
542 {
543 /*
544 * Save the returnStatus prior clearing operationInProgress or
545 * releasing the access semaphore in case it's overwritten.
546 */
547 status = object->common.returnStatus;
548
549 /* Mark that the current single-step or multi-step operation is done */
550 if (object->operationType != AESECB_OPERATION_TYPE_ENCRYPT_SEGMENTED)
551 {
552 AESCommonLPF3_clearOperationInProgress(&object->common);
553 }
554
555 AESCommonLPF3_cleanup(&object->common);
556
557 if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
558 {
559 object->callbackFxn(handle, status, object->operation, object->operationType);
560
561 /* Always return success in callback mode */
562 status = AESECB_STATUS_SUCCESS;
563 }
564 }
565 else if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_BLOCKING)
566 {
567 /* Ignore return value since timeout is infinite */
568 (void)SemaphoreP_pend((SemaphoreP_Handle)&CryptoResourceLPF3_operationSemaphore,
569 (uint32_t)SemaphoreP_WAIT_FOREVER);
570
571 status = object->common.returnStatus;
572 }
573 else /* AES_RETURN_BEHAVIOR_CALLBACK */
574 {
575 /* Success is always returned in callback mode */
576 status = AESECB_STATUS_SUCCESS;
577 }
578
579 return status;
580 }
581
582 /*
583 * ======== AESECB_setupEncrypt ========
584 */
AESECB_setupEncrypt(AESECB_Handle handle,const CryptoKey * key)585 int_fast16_t AESECB_setupEncrypt(AESECB_Handle handle, const CryptoKey *key)
586 {
587 DebugP_assert(handle);
588 int_fast16_t status = AESECB_STATUS_SUCCESS;
589 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
590
591 /*
592 * Key material pointer and length are not checked until adding or
593 * finalizing data.
594 */
595 if (key->encoding == CryptoKey_PLAINTEXT)
596 {
597 /* When using the AES driver with the LAES engine */
598 status = AESCommonLPF3_setupSegmentedOperation(&object->common, key);
599 }
600 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
601 else if (key->encoding == CryptoKey_PLAINTEXT_HSM)
602 {
603 if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
604 {
605 return AESECB_STATUS_ERROR;
606 }
607
608 /* A segmented operation may have been started but not finalized yet */
609 if (object->segmentedOperationInProgress)
610 {
611 return AESECB_STATUS_ERROR;
612 }
613
614 /* Make internal copy of crypto key */
615 object->common.key = *key;
616
617 /* returnStatus is only changed in the case of an error or cancellation */
618 object->common.returnStatus = AES_STATUS_SUCCESS;
619
620 object->segmentedOperationInProgress = true;
621 }
622 #endif
623 else
624 {
625 status = AESECB_STATUS_ERROR;
626 }
627
628 if (status == AES_STATUS_SUCCESS)
629 {
630 /*
631 * Initialize operation pointer to NULL in case AESECB_cancelOperation
632 * is called after AESECB_setupXXXX and callback should be skipped.
633 */
634 object->operation = NULL;
635 }
636
637 object->operationType = AESECB_OPERATION_TYPE_ENCRYPT_SEGMENTED;
638
639 return status;
640 }
641
642 /*
643 * ======== AESECB_setupDecrypt ========
644 */
AESECB_setupDecrypt(AESECB_Handle handle,const CryptoKey * key)645 int_fast16_t AESECB_setupDecrypt(AESECB_Handle handle, const CryptoKey *key)
646 {
647 DebugP_assert(handle);
648 DebugP_assert(key);
649
650 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
651 int_fast16_t status = AESECB_STATUS_SUCCESS;
652
653 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
654 if (key->encoding == CryptoKey_PLAINTEXT_HSM)
655 {
656 /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
657 if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
658 {
659 return AESECB_STATUS_ERROR;
660 }
661
662 /* A segmented operation may have been started but not finalized yet */
663 if (object->segmentedOperationInProgress)
664 {
665 return AESECB_STATUS_ERROR;
666 }
667
668 /* Make internal copy of crypto key */
669 object->common.key = *key;
670
671 /* returnStatus is only changed in the case of an error or cancellation */
672 object->common.returnStatus = AES_STATUS_SUCCESS;
673
674 /* Initialize operation pointer to NULL in case AESECB_cancelOperation
675 * is called after AESECB_setupXXXX and callback should be skipped.
676 */
677 object->operation = NULL;
678
679 object->operationType = AESECB_OPERATION_TYPE_DECRYPT_SEGMENTED;
680
681 object->segmentedOperationInProgress = true;
682 }
683 else
684 #endif
685 {
686 object->common.returnStatus = AESECB_STATUS_FEATURE_NOT_SUPPORTED;
687 status = AESECB_STATUS_FEATURE_NOT_SUPPORTED;
688 }
689
690 /* Save the error status in case addData or finalize is called afterward */
691
692 return status;
693 }
694
695 /*
696 * ======== AESECB_addData ========
697 */
AESECB_addData(AESECB_Handle handle,AESECB_Operation * operation)698 int_fast16_t AESECB_addData(AESECB_Handle handle, AESECB_Operation *operation)
699 {
700 DebugP_assert(handle);
701 DebugP_assert(operation);
702
703 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
704 int_fast16_t status;
705
706 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
707 if (operation->key->encoding == CryptoKey_PLAINTEXT_HSM)
708 {
709 return AESECBLPF3HSM_addData(handle, operation);
710 }
711 #endif
712
713 /*
714 * Assert the segmented operation was setup.
715 * LPF3 only supports ECB encryption.
716 */
717 DebugP_assert(object->operationType == AESECB_OPERATION_TYPE_ENCRYPT_SEGMENTED);
718
719 /* Check for previous failure or cancellation of segmented operation */
720 if (object->common.returnStatus != AESECB_STATUS_SUCCESS)
721 {
722 /*
723 * Return the status of the previous call.
724 * The callback function will not be executed.
725 */
726 return object->common.returnStatus;
727 }
728
729 status = AESECBLPF3_checkOperation(object, operation);
730
731 if (status != AESECB_STATUS_SUCCESS)
732 {
733 return status;
734 }
735
736 if (object->threadSafe)
737 {
738 if (!CryptoResourceLPF3_acquireLock(object->common.semaphoreTimeout))
739 {
740 return AESECB_STATUS_RESOURCE_UNAVAILABLE;
741 }
742
743 object->common.cryptoResourceLocked = true;
744 }
745
746 object->operation = operation;
747
748 return AESECBLPF3_startOperation(handle, operation);
749 }
750
751 /*
752 * ======== AESECB_finalize ========
753 */
AESECB_finalize(AESECB_Handle handle,AESECB_Operation * operation)754 int_fast16_t AESECB_finalize(AESECB_Handle handle, AESECB_Operation *operation)
755 {
756 DebugP_assert(handle);
757 DebugP_assert(operation);
758
759 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
760 int_fast16_t status;
761
762 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
763 if (operation->key->encoding == CryptoKey_PLAINTEXT_HSM)
764 {
765 return AESECBLPF3HSM_finalize(handle, operation);
766 }
767 #endif
768
769 /*
770 * Assert the segmented operation was setup.
771 * LPF3 only supports ECB encryption.
772 */
773 DebugP_assert(object->operationType == AESECB_OPERATION_TYPE_ENCRYPT_SEGMENTED);
774
775 /* Check for previous failure or cancellation of segmented operation */
776 if (object->common.returnStatus != AESECB_STATUS_SUCCESS)
777 {
778 /*
779 * Return the status of the previous call.
780 * The callback function will not be executed.
781 */
782 return object->common.returnStatus;
783 }
784
785 if (operation->inputLength > 0U)
786 {
787 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 0)
788 /* Check word-alignment of input & output pointers */
789 if (!IS_WORD_ALIGNED(operation->input) || !IS_WORD_ALIGNED(operation->output))
790 {
791 return AESECB_STATUS_UNALIGNED_IO_NOT_SUPPORTED;
792 }
793 #endif
794
795 /* Verify input length is a multiple of the AES block size */
796 if ((AES_NON_BLOCK_SIZE_MULTIPLE_LENGTH(operation->inputLength) > 0U))
797 {
798 return AESECB_STATUS_ERROR;
799 }
800
801 /* Check DMA xfer limit for blocking and callback modes */
802 if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) &&
803 !AESCommonLPF3_isDMALengthValid(operation->input, operation->output, operation->inputLength))
804 {
805 return AESECB_STATUS_ERROR;
806 }
807 }
808
809 AESECB_OperationType operationType = AESECB_OPERATION_TYPE_FINALIZE_ENCRYPT_SEGMENTED;
810
811 if (operation->inputLength > 0U)
812 {
813 /* Try and obtain access to the crypto module */
814 if (object->threadSafe)
815 {
816 if (!CryptoResourceLPF3_acquireLock(object->common.semaphoreTimeout))
817 {
818 return AESECB_STATUS_RESOURCE_UNAVAILABLE;
819 }
820
821 object->common.cryptoResourceLocked = true;
822 }
823
824 object->operationType = operationType;
825 object->operation = operation;
826
827 status = AESECBLPF3_startOperation(handle, operation);
828 }
829 else /* Operation was finalized without additional data to process */
830 {
831 status = object->common.returnStatus;
832
833 AESCommonLPF3_clearOperationInProgress(&object->common);
834
835 if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
836 {
837 object->callbackFxn(handle, status, operation, operationType);
838
839 /* Always return success in callback mode */
840 status = AESECB_STATUS_SUCCESS;
841 }
842 }
843
844 return status;
845 }
846
847 /*
848 * ======== AESECB_cancelOperation ========
849 */
AESECB_cancelOperation(AESECB_Handle handle)850 int_fast16_t AESECB_cancelOperation(AESECB_Handle handle)
851 {
852 DebugP_assert(handle);
853
854 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
855
856 /* Cancellation is only supported in callback mode */
857 if (object->common.returnBehavior != AES_RETURN_BEHAVIOR_CALLBACK)
858 {
859 return AESECB_STATUS_ERROR;
860 }
861
862 uintptr_t interruptKey = HwiP_disable();
863
864 /*
865 * Return success if there is no active operation to cancel.
866 * Do not execute the callback as it would have been executed already
867 * when the operation completed.
868 */
869 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
870 if (((object->common.key.encoding & CRYPTOKEY_HSM) == 0) && (!object->common.operationInProgress))
871 #else
872 if (!object->common.operationInProgress)
873 #endif
874 {
875 HwiP_restore(interruptKey);
876 return AESECB_STATUS_SUCCESS;
877 }
878
879 HwiP_restore(interruptKey);
880
881 /*
882 * Cancel DMA for input and output channels, clear operation in-progress,
883 * and releases crypto resource if necessary.
884 */
885 AESCommonLPF3_cancelOperation(&object->common, true);
886
887 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
888 if ((object->common.key.encoding & CRYPTOKEY_HSM))
889 {
890 /* Since the HSM cannot cancel an in-progress token, we must wait for the result to allow for
891 * subsequent token submissions to succeed.
892 */
893 (void)HSMLPF3_cancelOperation();
894
895 object->segmentedOperationInProgress = false;
896 }
897 #endif
898
899 /*
900 * Operation pointer could be NULL if a segmented operation was setup
901 * but neither AESECB_addData or AESECB_finalize was called.
902 */
903 if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK) && (object->operation != NULL))
904 {
905 /* Call the callback function provided by the application */
906 object->callbackFxn(handle, AESECB_STATUS_CANCELED, object->operation, object->operationType);
907 }
908
909 return AESECB_STATUS_SUCCESS;
910 }
911
912 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
913
914 /*
915 * ======== AESECBLPF3HSM_oneStepOperation ========
916 */
AESECBLPF3HSM_oneStepOperation(AESECB_Handle handle,AESECB_Operation * operation,AESECB_OperationType operationType)917 static int_fast16_t AESECBLPF3HSM_oneStepOperation(AESECB_Handle handle,
918 AESECB_Operation *operation,
919 AESECB_OperationType operationType)
920 {
921 DebugP_assert(handle);
922 DebugP_assert(operation);
923
924 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
925
926 /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
927 if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
928 {
929 return HSMLPF3_STATUS_ERROR;
930 }
931
932 /* A segmented operation may have been started but not finalized yet */
933 if (object->segmentedOperationInProgress)
934 {
935 return AESECB_STATUS_ERROR;
936 }
937
938 object->operation = operation;
939 object->operationType = operationType;
940
941 object->common.key = *(operation->key);
942 /* We will only change the returnStatus if there is an error or cancellation */
943 object->common.returnStatus = AESECB_STATUS_SUCCESS;
944
945 return AESECBLPF3HSM_processOneStep(handle);
946 }
947
948 /*
949 * ======== AESECBLPF3HSM_OneStepPostProcessing ========
950 */
AESECBLPF3HSM_OneStepPostProcessing(uintptr_t arg0)951 static inline void AESECBLPF3HSM_OneStepPostProcessing(uintptr_t arg0)
952 {
953 AESECB_Handle handle = (AESECB_Handle)arg0;
954 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
955 int_fast16_t status = AESECB_STATUS_ERROR;
956 int32_t physicalResult = HSMLPF3_getResultCode();
957 int32_t tokenResult = physicalResult & HSMLPF3_RETVAL_MASK;
958
959 if (tokenResult == EIP130TOKEN_RESULT_SUCCESS)
960 {
961 status = AESECB_STATUS_SUCCESS;
962 }
963
964 object->common.returnStatus = status;
965
966 HSMLPF3_releaseLock();
967
968 Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
969
970 if ((object->operationType == AESECB_OPERATION_TYPE_FINALIZE_ENCRYPT_SEGMENTED) ||
971 (object->operationType == AESECB_OPERATION_TYPE_FINALIZE_DECRYPT_SEGMENTED) ||
972 (object->operationType == AESECB_OPERATION_TYPE_ENCRYPT) ||
973 (object->operationType == AESECB_OPERATION_TYPE_DECRYPT))
974 {
975 object->segmentedOperationInProgress = false;
976 }
977
978 if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
979 {
980 object->callbackFxn(handle, object->common.returnStatus, object->operation, object->operationType);
981 }
982 }
983
AESECBLPF3HSM_processOneStep(AESECB_Handle handle)984 static int_fast16_t AESECBLPF3HSM_processOneStep(AESECB_Handle handle)
985 {
986 int_fast16_t status = AESECB_STATUS_ERROR;
987 int_fast16_t hsmRetval = HSMLPF3_STATUS_ERROR;
988 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
989
990 if (!HSMLPF3_acquireLock(SemaphoreP_NO_WAIT, (uintptr_t)handle))
991 {
992 return AESECB_STATUS_RESOURCE_UNAVAILABLE;
993 }
994
995 Power_setConstraint(PowerLPF3_DISALLOW_STANDBY);
996
997 HSMLPF3_constructAESECBOneStepPhysicalToken(object);
998
999 hsmRetval = HSMLPF3_submitToken((HSMLPF3_ReturnBehavior)object->common.returnBehavior,
1000 AESECBLPF3HSM_OneStepPostProcessing,
1001 (uintptr_t)handle);
1002
1003 if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
1004 {
1005 hsmRetval = HSMLPF3_waitForResult();
1006
1007 if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
1008 {
1009 status = object->common.returnStatus;
1010 }
1011 }
1012
1013 if (hsmRetval != HSMLPF3_STATUS_SUCCESS)
1014 {
1015 Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
1016
1017 HSMLPF3_releaseLock();
1018 }
1019
1020 return status;
1021 }
1022
AESECBLPF3HSM_addData(AESECB_Handle handle,AESECB_Operation * operation)1023 static int_fast16_t AESECBLPF3HSM_addData(AESECB_Handle handle, AESECB_Operation *operation)
1024 {
1025 DebugP_assert(handle);
1026 DebugP_assert(operation);
1027
1028 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
1029
1030 /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
1031 if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
1032 {
1033 return AESECB_STATUS_ERROR;
1034 }
1035
1036 /*
1037 * Assert the segmented operation was setup.
1038 * LPF3 only supports ECB encryption.
1039 */
1040 DebugP_assert((object->operationType == AESECB_OPERATION_TYPE_ENCRYPT_SEGMENTED) ||
1041 (object->operationType == AESECB_OPERATION_TYPE_DECRYPT_SEGMENTED));
1042
1043 /* Check for previous failure or cancellation of segmented operation */
1044 if (object->common.returnStatus != AESECB_STATUS_SUCCESS)
1045 {
1046 /*
1047 * Return the status of the previous call.
1048 * The callback function will not be executed.
1049 */
1050 return object->common.returnStatus;
1051 }
1052
1053 object->operation = operation;
1054
1055 return AESECBLPF3HSM_processOneStep(handle);
1056 }
1057
AESECBLPF3HSM_finalize(AESECB_Handle handle,AESECB_Operation * operation)1058 static int_fast16_t AESECBLPF3HSM_finalize(AESECB_Handle handle, AESECB_Operation *operation)
1059 {
1060 DebugP_assert(handle);
1061 DebugP_assert(operation);
1062
1063 AESECBLPF3_Object *object = AESEBCLPF3_getObject(handle);
1064 int_fast16_t status;
1065
1066 /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
1067 if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
1068 {
1069 return AESECB_STATUS_ERROR;
1070 }
1071
1072 /*
1073 * Assert the segmented operation was setup.
1074 * LPF3 only supports ECB encryption.
1075 */
1076 DebugP_assert((object->operationType == AESECB_OPERATION_TYPE_ENCRYPT_SEGMENTED) ||
1077 (object->operationType == AESECB_OPERATION_TYPE_DECRYPT_SEGMENTED));
1078
1079 /* Check for previous failure or cancellation of segmented operation */
1080 if (object->common.returnStatus != AESECB_STATUS_SUCCESS)
1081 {
1082 /*
1083 * Return the status of the previous call.
1084 * The callback function will not be executed.
1085 */
1086 return object->common.returnStatus;
1087 }
1088
1089 if (object->operationType == AESECB_OPERATION_TYPE_ENCRYPT_SEGMENTED)
1090 {
1091 object->operationType = AESECB_OPERATION_TYPE_FINALIZE_ENCRYPT_SEGMENTED;
1092 }
1093 else if (object->operationType == AESECB_OPERATION_TYPE_DECRYPT_SEGMENTED)
1094 {
1095 object->operationType = AESECB_OPERATION_TYPE_FINALIZE_DECRYPT_SEGMENTED;
1096 }
1097
1098 if (operation->inputLength > 0U)
1099 {
1100 object->operation = operation;
1101
1102 status = AESECBLPF3HSM_processOneStep(handle);
1103 }
1104 else /* Operation was finalized without additional data to process */
1105 {
1106 /* Save the object's returnStatus in case it is
1107 * overwritten during setup of a new segmented operation
1108 * after the operationInProgress flag is cleared.
1109 */
1110 status = object->common.returnStatus;
1111
1112 object->segmentedOperationInProgress = false;
1113
1114 if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
1115 {
1116 object->callbackFxn(handle, status, operation, object->operationType);
1117
1118 /* Always return success in callback mode */
1119 status = AESECB_STATUS_SUCCESS;
1120 }
1121 }
1122
1123 return status;
1124 }
1125
1126 #endif
1127