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