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/aesctr/AESCTRLPF3.h>
38 #include <ti/drivers/AESCommon.h>
39 #include <ti/drivers/cryptoutils/aes/AESCommonLPF3.h>
40 #include <ti/drivers/cryptoutils/cryptokey/CryptoKey.h>
41 #include <ti/drivers/cryptoutils/sharedresources/CryptoResourceLPF3.h>
42 #include <ti/drivers/dma/UDMALPF3.h>
43 
44 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
45     #include <ti/drivers/cryptoutils/hsm/HSMLPF3.h>
46     #include <third_party/hsmddk/include/Integration/Adapter_DriverInit/incl/api_driver_init.h>
47     #include <third_party/hsmddk/include/Integration/Adapter_VEX/incl/adapter_vex.h>
48     #include <third_party/hsmddk/include/Integration/Adapter_PSA/incl/adapter_psa_exchangetoken.h>
49     #include <third_party/hsmddk/include/Integration/Adapter_PSA/incl/adapter_psa_asset.h>
50     #include <third_party/hsmddk/include/Kit/EIP130/TokenHelper/incl/eip130_token_result.h>
51     #include <third_party/hsmddk/include/Kit/EIP130/TokenHelper/incl/eip130_token_asset.h>
52 #endif
53 
54 #include <ti/drivers/dpl/DebugP.h>
55 #include <ti/drivers/dpl/HwiP.h>
56 #include <ti/drivers/dpl/SemaphoreP.h>
57 
58 #include <ti/devices/DeviceFamily.h>
59 #include DeviceFamily_constructPath(driverlib/aes.h)
60 #include DeviceFamily_constructPath(inc/hw_aes.h)
61 #include DeviceFamily_constructPath(inc/hw_ints.h)
62 
63 /**
64  * The threshold at which blocking and callback mode transfers will utilize DMA.
65  * For data lengths below this threshold, polling CPU R/W will be used instead
66  * of DMA. With task switching and interrupt overhead, it is inefficient to
67  * utilize DMA for shorter length operations.
68  * The threshold value must be a multiple of AES_BLOCK_SIZE.
69  */
70 #define AESCTRLPF3_DMA_SIZE_THRESHOLD (1U * AES_BLOCK_SIZE)
71 
72 /*
73  * AES DMA configuration to use when data length is not a block multiple and
74  * the partial block of input/output remaining will be completed via CPU R/W.
75  *
76  * DMA channel A moves m[1:x] into TXTX when ECB completes
77  *
78  *    ADRCHA = TXTX0
79  *    TRGCHA = ECBDONE
80  *
81  * DMA channel B moves ciphertext[1:x] to memory after channel A has written TXTX3.
82  *
83  *    ADRCHB = TXT0
84  *    TRGCHB = WRTXT3
85  */
86 #if DeviceFamily_PARENT == DeviceFamily_PARENT_CC23X0
87     #define AESCTRLPF3_DMA_CONFIG                                                                            \
88         ((uint32_t)AES_DMA_ADRCHA_TXTX0 | (uint32_t)AES_DMA_TRGCHA_AESDONE | (uint32_t)AES_DMA_ADRCHB_TXT0 | \
89          (uint32_t)AES_DMA_TRGCHB_WRTXT3)
90 #elif DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX
91     #define AESCTRLPF3_DMA_CONFIG                                                                            \
92         ((uint32_t)AES_DMA_ADRCHA_TXTX0 | (uint32_t)AES_DMA_TRGCHA_ECBDONE | (uint32_t)AES_DMA_ADRCHB_TXT0 | \
93          (uint32_t)AES_DMA_TRGCHB_WRTXT3)
94 #else
95     #error "Unsupported DeviceFamily_Parent for AESCTRLPF3!"
96 #endif
97 
98 /*
99  * AES DMA configuration to use when data length is exactly a block multiple.
100  *
101  * DMA channel A moves m[1:x] into TXTX when ECB completes
102  *
103  *    ADRCHA = TXTX0
104  *    TRGCHA = ECBDONE
105  *    DONEACT = GATE_TRGECB_ON_CHA (to avoid spurious last ECB using DMA)
106  *
107  * DMA channel B moves ciphertext[1:x] to memory after channel A has written TXTX3.
108  *
109  *    ADRCHB = TXT0
110  *    TRGCHB = WRTXT3
111  */
112 #if DeviceFamily_PARENT == DeviceFamily_PARENT_CC23X0
113     #define AESCTRLPF3_GATE_CHA_DMA_CONFIG (AESCTRLPF3_DMA_CONFIG | (uint32_t)AES_DMA_DONEACT_GATE_TRGAES_ON_CHA)
114 #elif DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX
115     #define AESCTRLPF3_GATE_CHA_DMA_CONFIG (AESCTRLPF3_DMA_CONFIG | (uint32_t)AES_DMA_DONEACT_GATE_TRGECB_ON_CHA)
116 #else
117     #error "Unsupported DeviceFamily_Parent for AESCTRLPF3!"
118 #endif
119 
120 /* Forward declarations */
121 static void AESCTRLPF3_initCounter(AESCTRLPF3_Object *object, const uint8_t initialCounter[AES_BLOCK_SIZE]);
122 static int_fast16_t AESCTRLPF3_oneStepOperation(AESCTR_Handle handle,
123                                                 AESCTR_OneStepOperation *operation,
124                                                 AESCTR_OperationType operationType);
125 static int_fast16_t AESCTRLPF3_startOperation(AESCTR_Handle handle, bool isOneStepOrFinalOperation);
126 static int_fast16_t AESCTRLPF3_waitForResult(AESCTR_Handle handle);
127 
128 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
129 static int_fast16_t AESCTRLPF3HSM_oneStepOperation(AESCTR_Handle handle,
130                                                    AESCTR_OneStepOperation *operation,
131                                                    AESCTR_OperationType operationType);
132 static int_fast16_t AESCTRLPF3HSM_processOneStepOperation(AESCTR_Handle handle);
133 
134 int_fast16_t AESCTRLPF3HSM_addData(AESCTR_Handle handle, AESCTR_SegmentedOperation *operation);
135 
136 int_fast16_t AESCTRLPF3HSM_finalize(AESCTR_Handle handle, AESCTR_SegmentedOperation *operation);
137 #endif
138 
139 /*
140  *  ======== AESCTRLPF3_getObject ========
141  */
AESCTRLPF3_getObject(AESCTR_Handle handle)142 static inline AESCTRLPF3_Object *AESCTRLPF3_getObject(AESCTR_Handle handle)
143 {
144     AESCTRLPF3_Object *object = (AESCTRLPF3_Object *)handle->object;
145     DebugP_assert(object);
146 
147     return object;
148 }
149 
150 /*
151  *  ======== AESCTRLPF3_hwiFxn ========
152  */
AESCTRLPF3_hwiFxn(uintptr_t arg0)153 static void AESCTRLPF3_hwiFxn(uintptr_t arg0)
154 {
155     AESCTR_Handle handle      = (AESCTR_Handle)arg0;
156     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
157 
158     /*
159      * Only the output channel B interrupt is enabled.
160      */
161     uint32_t intStatus = AESGetMaskedInterruptStatus();
162 
163     /* Disable DMA, clear interupts, and release power constraint */
164     AESCommonLPF3_cleanupHwi(&object->common);
165 
166     if ((intStatus & (uint32_t)AES_MIS_CHBDONE_M) != (uint32_t)0U)
167     {
168         UDMALPF3_clearInterrupt(AESCommonLPF3_DMA_CHB_BITMASK);
169 
170         if ((object->inputLengthRemaining > 0U) && (object->inputLengthRemaining < AESCTRLPF3_DMA_SIZE_THRESHOLD))
171         {
172             /* Use CPU R/W to complete the CTR operation */
173             AESCTRLPF3_processData(&object->input[object->inputLength - object->inputLengthRemaining],
174                                    &object->output[object->inputLength - object->inputLengthRemaining],
175                                    object->inputLengthRemaining,
176                                    true);
177 
178             object->inputLengthRemaining = 0U;
179         }
180 
181         if (object->inputLengthRemaining > 0U)
182         {
183             /*
184              * If DMA Ping-Pong mode is supported in the future:
185              *  - Set power contraint
186              *  - Setup next DMA control struct to continue CTR operation
187              */
188         }
189 
190         /* Save the last counter value from the AES engine */
191         AESCTRLPF3_readCounter((uint32_t *)&object->counter[0]);
192 
193         /* Check if one-step or final operation */
194         if ((object->operationType & AESCTR_OP_FLAG_SEGMENTED) == 0)
195         {
196             AESCommonLPF3_clearOperationInProgress(&object->common);
197         }
198 
199         /* Cleanup and release crypto resource lock */
200         AESCommonLPF3_cleanup(&object->common);
201 
202         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_BLOCKING)
203         {
204             /* Unblock the pending task to signal that the operation is complete */
205             SemaphoreP_post(&CryptoResourceLPF3_operationSemaphore);
206         }
207         else
208         {
209             /* Call the callback function provided by the application */
210             object->callbackFxn(handle, object->common.returnStatus, object->operation, object->operationType);
211         }
212     }
213 }
214 
215 /*
216  *  ======== AESCTR_init ========
217  */
AESCTR_init(void)218 void AESCTR_init(void)
219 {
220 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
221     HSMLPF3_constructRTOSObjects();
222 #endif
223     AESCommonLPF3_init();
224 }
225 
226 /*
227  *  ======== AESCTR_construct ========
228  */
AESCTR_construct(AESCTR_Config * config,const AESCTR_Params * params)229 AESCTR_Handle AESCTR_construct(AESCTR_Config *config, const AESCTR_Params *params)
230 {
231     DebugP_assert(config);
232 
233     int_fast16_t status;
234     AESCTR_Handle handle      = config;
235     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
236 
237 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
238     /* Initialize and boot HSM */
239     if (HSMLPF3_init() != HSMLPF3_STATUS_SUCCESS)
240     {
241         /* Upon HSM Boot failure, the AES-CCM Driver stores the failure status in the object
242          * This is done so that users of the AES-CCM Driver do not get a NULL handle and still can use
243          * the driver in LAES mode.
244          */
245         object->hsmStatus = HSMLPF3_STATUS_ERROR;
246     }
247     else
248     {
249         object->hsmStatus = HSMLPF3_STATUS_SUCCESS;
250     }
251 
252     object->segmentedOperationInProgress = false;
253 #endif
254 
255     /* If params are NULL, use defaults */
256     if (params == NULL)
257     {
258         params = &AESCTR_defaultParams;
259     }
260 
261     DebugP_assert((params->returnBehavior != AESCTR_RETURN_BEHAVIOR_CALLBACK) || (params->callbackFxn != NULL));
262 
263     object->callbackFxn = params->callbackFxn;
264     object->threadSafe  = true;
265 
266     status = AESCommonLPF3_construct(&object->common, (AES_ReturnBehavior)params->returnBehavior, params->timeout);
267 
268     if (status != AES_STATUS_SUCCESS)
269     {
270         handle = NULL;
271     }
272 
273     return handle;
274 }
275 
276 /*
277  *  ======== AESCTR_close ========
278  */
AESCTR_close(AESCTR_Handle handle)279 void AESCTR_close(AESCTR_Handle handle)
280 {
281     DebugP_assert(handle);
282 
283     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
284 
285     AESCommonLPF3_close(&object->common);
286 }
287 
288 /*
289  *  ======== AESCTR_oneStepEncrypt ========
290  */
AESCTR_oneStepEncrypt(AESCTR_Handle handle,AESCTR_OneStepOperation * operationStruct)291 int_fast16_t AESCTR_oneStepEncrypt(AESCTR_Handle handle, AESCTR_OneStepOperation *operationStruct)
292 {
293     int_fast16_t status;
294 
295     if (operationStruct->key->encoding == CryptoKey_PLAINTEXT || operationStruct->key->encoding == CryptoKey_KEYSTORE)
296     {
297         status = AESCTRLPF3_oneStepOperation(handle, operationStruct, AESCTR_OPERATION_TYPE_ENCRYPT);
298     }
299 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
300     else if (operationStruct->key->encoding == CryptoKey_PLAINTEXT_HSM)
301     {
302         status = AESCTRLPF3HSM_oneStepOperation(handle, operationStruct, AESCTR_OPERATION_TYPE_ENCRYPT);
303     }
304 #endif
305     else
306     {
307         status = AESCTR_STATUS_ERROR;
308     }
309     return status;
310 }
311 
312 /*
313  *  ======== AESCTR_oneStepDecrypt ========
314  */
AESCTR_oneStepDecrypt(AESCTR_Handle handle,AESCTR_OneStepOperation * operationStruct)315 int_fast16_t AESCTR_oneStepDecrypt(AESCTR_Handle handle, AESCTR_OneStepOperation *operationStruct)
316 {
317     int_fast16_t status;
318 
319     if (operationStruct->key->encoding == CryptoKey_PLAINTEXT || operationStruct->key->encoding == CryptoKey_KEYSTORE)
320     {
321         status = AESCTRLPF3_oneStepOperation(handle, operationStruct, AESCTR_OPERATION_TYPE_DECRYPT);
322     }
323 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
324     else if (operationStruct->key->encoding == CryptoKey_PLAINTEXT_HSM)
325     {
326         status = AESCTRLPF3HSM_oneStepOperation(handle, operationStruct, AESCTR_OPERATION_TYPE_DECRYPT);
327     }
328 #endif
329     else
330     {
331         status = AESCTR_STATUS_ERROR;
332     }
333     return status;
334 }
335 
336 /*
337  *  ======== AESCTRLPF3_oneStepOperation ========
338  */
AESCTRLPF3_oneStepOperation(AESCTR_Handle handle,AESCTR_OneStepOperation * operation,AESCTR_OperationType operationType)339 static int_fast16_t AESCTRLPF3_oneStepOperation(AESCTR_Handle handle,
340                                                 AESCTR_OneStepOperation *operation,
341                                                 AESCTR_OperationType operationType)
342 {
343     DebugP_assert(handle);
344     DebugP_assert(operation);
345     DebugP_assert(operation->key);
346     /* No need to assert operationType since we control it within the driver */
347 
348     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
349     int_fast16_t status;
350 
351 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 0)
352     /* Check word-alignment of input & output pointers */
353     if (!IS_WORD_ALIGNED(operation->input) || !IS_WORD_ALIGNED(operation->output))
354     {
355         return AESCTR_STATUS_UNALIGNED_IO_NOT_SUPPORTED;
356     }
357 #endif
358 
359     /* Check DMA xfer limit for blocking and callback modes */
360     if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) &&
361         !AESCommonLPF3_isDMALengthValid(operation->input, operation->output, operation->inputLength))
362     {
363         return AESCTR_STATUS_ERROR;
364     }
365 
366     /* Verify input length is non-zero */
367     if (operation->inputLength == 0U)
368     {
369         return AESCTR_STATUS_ERROR;
370     }
371 
372     /*
373      * Check if there is no operation already in progress for this driver
374      * instance, and then mark the current operation to be in progress.
375      */
376     status = AESCommonLPF3_setOperationInProgress(&object->common);
377 
378     if (status != AESCTR_STATUS_SUCCESS)
379     {
380         return status;
381     }
382 
383     if (object->threadSafe)
384     {
385         if (!CryptoResourceLPF3_acquireLock(object->common.semaphoreTimeout))
386         {
387             AESCommonLPF3_clearOperationInProgress(&object->common);
388             return AESCTR_STATUS_RESOURCE_UNAVAILABLE;
389         }
390 
391         object->common.cryptoResourceLocked = true;
392     }
393 
394     object->operation           = (AESCTR_OperationUnion *)operation;
395     object->operationType       = operationType;
396     /* We will only change the returnStatus if there is an error or cancellation */
397     object->common.returnStatus = AESCTR_STATUS_SUCCESS;
398 
399     /* Make internal copy of operational params */
400     object->common.key           = *(operation->key);
401     object->input                = operation->input;
402     object->inputLength          = operation->inputLength;
403     object->inputLengthRemaining = operation->inputLength;
404     object->output               = operation->output;
405 
406     AESCTRLPF3_initCounter(object, &operation->initialCounter[0]);
407 
408     status = AESCTRLPF3_startOperation(handle, true);
409 
410     return status;
411 }
412 
413 /*
414  *  ======== AESCTRLPF3_initCounter ========
415  */
AESCTRLPF3_initCounter(AESCTRLPF3_Object * object,const uint8_t initialCounter[AES_BLOCK_SIZE])416 static void AESCTRLPF3_initCounter(AESCTRLPF3_Object *object, const uint8_t initialCounter[AES_BLOCK_SIZE])
417 {
418     if (initialCounter != NULL)
419     {
420         (void)memcpy((void *)&object->counter[0], (void *)&initialCounter[0], sizeof(object->counter));
421     }
422     else
423     {
424         (void)memset((void *)&object->counter[0], 0, sizeof(object->counter));
425     }
426 }
427 
428 /*
429  *  ======== AESCTRLPF3_startOperation ========
430  */
AESCTRLPF3_startOperation(AESCTR_Handle handle,bool isOneStepOrFinalOperation)431 static int_fast16_t AESCTRLPF3_startOperation(AESCTR_Handle handle, bool isOneStepOrFinalOperation)
432 {
433     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
434     int_fast16_t status       = AESCTR_STATUS_SUCCESS;
435     size_t bytesProcessed;
436 
437     /* Set up the key and AES engine to begin an operation */
438     AESCommonLPF3_setupOperation(&object->common.key, AESCTRLPF3_DEFAULT_AUTOCFG);
439 
440     /*
441      * Process all operations with data length less than the DMA size
442      * threshold as a polling mode operation.
443      */
444     if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_POLLING) ||
445         (object->inputLength < AESCTRLPF3_DMA_SIZE_THRESHOLD))
446     {
447         /* Write the counter value to the AES engine to trigger first encryption */
448         AESCTRLPF3_writeCounter((uint32_t *)&object->counter[0]);
449 
450         /* Process all blocks with CPU R/W */
451         AESCTRLPF3_processData(object->input, object->output, object->inputLength, isOneStepOrFinalOperation);
452 
453         object->inputLengthRemaining = 0U;
454     }
455     else
456     {
457         /*
458          * We need to set the HWI function and priority since the same physical
459          * interrupt is shared by multiple drivers and they all need to coexist.
460          * Whenever a driver starts an operation, it registers its HWI callback
461          * with the OS.
462          */
463         AESCTRLPF3_HWAttrs const *hwAttrs = handle->hwAttrs;
464         AESCommonLPF3_setupHwi(AESCTRLPF3_hwiFxn, (uintptr_t)handle, hwAttrs->intPriority);
465 
466         bytesProcessed = AESCTRLPF3_configDataDMA(&object->common, object->input, object->output, object->inputLength);
467 
468         object->inputLengthRemaining -= bytesProcessed;
469 
470         /* Write the counter value to the AES engine to trigger first encryption */
471         AESCTRLPF3_writeCounter((uint32_t *)&object->counter[0]);
472     }
473 
474     status = AESCTRLPF3_waitForResult(handle);
475 
476     return status;
477 }
478 
479 /*
480  *  ======== AESCTRLPF3_configDataDMA ========
481  */
AESCTRLPF3_configDataDMA(AESCommonLPF3_Object * object,const uint8_t * input,uint8_t * output,size_t inputLength)482 size_t AESCTRLPF3_configDataDMA(AESCommonLPF3_Object *object, const uint8_t *input, uint8_t *output, size_t inputLength)
483 {
484     size_t blockSizeDataLen = AES_BLOCK_SIZE_MULTIPLE_LENGTH(inputLength);
485 
486     /* Clear BUSHALT when using DMA */
487     AESClearAUTOCFGBusHalt();
488 
489     /* Setup DMA configuration and set power constraint */
490     if (blockSizeDataLen == inputLength)
491     {
492         AESCommonLPF3_setupDMA(object, AESCTRLPF3_GATE_CHA_DMA_CONFIG);
493     }
494     else
495     {
496         AESCommonLPF3_setupDMA(object, AESCTRLPF3_DMA_CONFIG);
497     }
498 
499     /*
500      * Only full blocks of data can be processed with DMA because the trigger
501      * for DMA channel B (output) is based on channel A (input) writing the
502      * last word of the TXTX register
503      */
504     AESCommonLPF3_configInputDMA(input, blockSizeDataLen);
505     AESCommonLPF3_configOutputDMA(output, blockSizeDataLen);
506 
507     /* Enable interrupt upon output DMA done */
508     AESSetIMASK((uint32_t)AES_IMASK_CHBDONE_M);
509 
510     return blockSizeDataLen;
511 }
512 
513 /*
514  *  ======== AESCTRLPF3_processData ========
515  */
AESCTRLPF3_processData(const uint8_t * input,uint8_t * output,size_t inputLength,bool isOneStepOrFinalOperation)516 void AESCTRLPF3_processData(const uint8_t *input, uint8_t *output, size_t inputLength, bool isOneStepOrFinalOperation)
517 {
518     size_t bytesProcessed                 = 0;
519     size_t bytesRemaining                 = inputLength;
520     size_t blockSizeAlignedBytesRemaining = AES_BLOCK_SIZE_MULTIPLE_LENGTH(inputLength);
521 
522     if (blockSizeAlignedBytesRemaining > 0U)
523     {
524         bytesRemaining -= blockSizeAlignedBytesRemaining;
525 
526 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 1)
527         if (!IS_WORD_ALIGNED(input) || !IS_WORD_ALIGNED(output))
528         {
529             do
530             {
531     #ifdef AES_BUSHALT_DISABLED
532                 /* Wait for encryption to complete */
533                 while (AESGetStatus() != (uint32_t)AES_STA_STATE_IDLE) {}
534     #endif
535 
536                 if ((blockSizeAlignedBytesRemaining == AES_BLOCK_SIZE) && (bytesRemaining == 0U))
537                 {
538                     /*
539                      * Do not auto-trigger encrypt and increment of counter
540                      * value for last block of data.
541                      */
542                     AESSetAUTOCFG(AESCTRLPF3_LAST_BLOCK_AUTOCFG);
543                 }
544 
545                 /* XOR input data with encrypted counter block to form ciphertext */
546                 AESWriteTXTXOR(&input[bytesProcessed]);
547 
548                 /* Read the output ciphertext and trigger the encryption of the next counter block */
549                 AESReadTXT(&output[bytesProcessed]);
550 
551                 bytesProcessed += AES_BLOCK_SIZE;
552                 blockSizeAlignedBytesRemaining -= AES_BLOCK_SIZE;
553 
554             } while (blockSizeAlignedBytesRemaining > 0U);
555         }
556         else
557 #endif
558         {
559             /*
560              * This optimization for word-aligned input & output is used to improve
561              * performance for AES-CCM to ensure BLE stack can meet timing
562              * requirements.
563              */
564 
565             /* Safe to cast word-aligned input & output pointers */
566             const uint32_t *input32 = (const uint32_t *)input;
567             uint32_t *output32      = (uint32_t *)output;
568             size_t inputBlocks      = AES_GET_NUM_BLOCKS(blockSizeAlignedBytesRemaining);
569 
570             if (!isOneStepOrFinalOperation && (bytesRemaining == 0U))
571             {
572                 if (inputBlocks > 1U)
573                 {
574                     /* Process all data except the last block */
575                     AESProcessAlignedBlocksCTR(input32, output32, (uint32_t)inputBlocks - (uint32_t)1U);
576 
577                     input32  = (const uint32_t *)&input[blockSizeAlignedBytesRemaining - AES_BLOCK_SIZE];
578                     output32 = (uint32_t *)&output[blockSizeAlignedBytesRemaining - AES_BLOCK_SIZE];
579                 }
580 
581                 /*
582                  * Do not auto-trigger encrypt and increment of counter
583                  * value for last block of data.
584                  */
585                 AESSetAUTOCFG(AESCTRLPF3_LAST_BLOCK_AUTOCFG);
586 
587                 /* Process last block of data */
588                 AESProcessAlignedBlocksCTR(input32, output32, (uint32_t)1U);
589             }
590             else
591             {
592                 /*
593                  * Process all the data. This will trigger a spurious encryption
594                  * when reading the final output which will be aborted during cleanup.
595                  */
596                 AESProcessAlignedBlocksCTR(input32, output32, inputBlocks);
597             }
598 
599             bytesProcessed = blockSizeAlignedBytesRemaining;
600         }
601     }
602 
603     /* Process any remaining partial blocks of input data */
604     if (bytesRemaining > 0U)
605     {
606 #ifdef AES_BUSHALT_DISABLED
607         /* Wait for encryption of counter block to complete */
608         while (AESGetStatus() != (uint32_t)AES_STA_STATE_IDLE) {}
609 #endif
610         size_t i;
611 
612         /* This code is faster than calling memcpy() twice */
613         for (i = 0U; i < bytesRemaining; i++)
614         {
615             volatile uint8_t *regTXTX = (volatile uint8_t *)(AES_BASE + AES_O_TXTX0);
616             volatile uint8_t *regTXT  = (volatile uint8_t *)(AES_BASE + AES_O_TXT0);
617 
618             /* Write TXTX register to XOR input with previously encrypted counter block */
619             regTXTX[i] = input[bytesProcessed + i];
620 
621             /* Read output from TXT register */
622             output[bytesProcessed + i] = regTXT[i];
623         }
624     }
625 }
626 
627 /*
628  *  ======== AESCTRLPF3_waitForResult ========
629  */
AESCTRLPF3_waitForResult(AESCTR_Handle handle)630 static int_fast16_t AESCTRLPF3_waitForResult(AESCTR_Handle handle)
631 {
632     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
633     int_fast16_t status;
634 
635     if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_POLLING) ||
636         (object->inputLength < AESCTRLPF3_DMA_SIZE_THRESHOLD))
637     {
638         /* Save the last counter value from the AES engine */
639         AESCTRLPF3_readCounter((uint32_t *)&object->counter[0]);
640 
641         /*
642          * Save the object's returnStatus before clearing operationInProgress or
643          * posting the access semaphore in case it is overwritten.
644          */
645         status = object->common.returnStatus;
646 
647         if ((object->operationType & AESCTR_OP_FLAG_SEGMENTED) == 0U)
648         {
649             /* One-step or finalization operation is complete */
650             AESCommonLPF3_clearOperationInProgress(&object->common);
651         }
652 
653         AESCommonLPF3_cleanup(&object->common);
654 
655         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
656         {
657             object->callbackFxn(handle, status, object->operation, object->operationType);
658 
659             /* Always return success in callback mode */
660             status = AESCTR_STATUS_SUCCESS;
661         }
662     }
663     else if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_BLOCKING)
664     {
665         /* Ignore return value since timeout is infinite */
666         (void)SemaphoreP_pend((SemaphoreP_Handle)&CryptoResourceLPF3_operationSemaphore,
667                               (uint32_t)SemaphoreP_WAIT_FOREVER);
668 
669         status = object->common.returnStatus;
670     }
671     else /* AESCTR_RETURN_BEHAVIOR_CALLBACK */
672     {
673         /* Success is always returned in callback mode */
674         status = AESCTR_STATUS_SUCCESS;
675     }
676 
677     return status;
678 }
679 
680 /*
681  *  ======== AESCTR_addData ========
682  */
AESCTR_addData(AESCTR_Handle handle,AESCTR_SegmentedOperation * operation)683 int_fast16_t AESCTR_addData(AESCTR_Handle handle, AESCTR_SegmentedOperation *operation)
684 {
685     DebugP_assert(handle);
686     DebugP_assert(operation);
687 
688     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
689     int_fast16_t status;
690 
691 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
692     if (object->common.key.encoding == CryptoKey_PLAINTEXT_HSM)
693     {
694         return AESCTRLPF3HSM_addData(handle, operation);
695     }
696 #endif
697 
698     /* Assert the segmented operation was setup */
699     DebugP_assert((object->operationType == AESCTR_OPERATION_TYPE_ENCRYPT_SEGMENTED) ||
700                   (object->operationType == AESCTR_OPERATION_TYPE_DECRYPT_SEGMENTED));
701 
702     /* Check for previous failure or cancellation of segmented operation */
703     if (object->common.returnStatus != AESCTR_STATUS_SUCCESS)
704     {
705         /*
706          * Return the status of the previous call.
707          * The callback function will not be executed.
708          */
709         return object->common.returnStatus;
710     }
711 
712 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 0)
713     /* Check word-alignment of input & output pointers */
714     if (!IS_WORD_ALIGNED(operation->input) || !IS_WORD_ALIGNED(operation->output))
715     {
716         return AESCTR_STATUS_UNALIGNED_IO_NOT_SUPPORTED;
717     }
718 #endif
719 
720     /* Verify the input length is non-zero and a multiple of the block size */
721     if ((operation->inputLength == 0U) || ((operation->inputLength & AES_NON_BLOCK_SIZE_MULTIPLE_MASK) != 0U))
722     {
723         return AESCTR_STATUS_ERROR;
724     }
725 
726     /* Check DMA xfer limit for blocking and callback modes */
727     if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) &&
728         !AESCommonLPF3_isDMALengthValid(operation->input, operation->output, operation->inputLength))
729     {
730         return AESCTR_STATUS_ERROR;
731     }
732 
733     if (object->threadSafe)
734     {
735         if (!CryptoResourceLPF3_acquireLock(object->common.semaphoreTimeout))
736         {
737             return AESCTR_STATUS_RESOURCE_UNAVAILABLE;
738         }
739 
740         object->common.cryptoResourceLocked = true;
741     }
742 
743     object->operation = (AESCTR_OperationUnion *)operation;
744 
745     /* Make internal copy of operational params */
746     object->input                = operation->input;
747     object->inputLength          = operation->inputLength;
748     object->inputLengthRemaining = operation->inputLength;
749     object->output               = operation->output;
750 
751     status = AESCTRLPF3_startOperation(handle, false);
752 
753     return status;
754 }
755 
756 /*
757  *  ======== AESCTR_finalize ========
758  */
AESCTR_finalize(AESCTR_Handle handle,AESCTR_SegmentedOperation * operation)759 int_fast16_t AESCTR_finalize(AESCTR_Handle handle, AESCTR_SegmentedOperation *operation)
760 {
761     DebugP_assert(handle);
762     DebugP_assert(operation);
763 
764     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
765     AESCTR_OperationType operationType;
766     int_fast16_t status;
767 
768 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
769     if (object->common.key.encoding == CryptoKey_PLAINTEXT_HSM)
770     {
771         return AESCTRLPF3HSM_finalize(handle, operation);
772     }
773 #endif
774 
775     /* Assert the segmented operation was setup */
776     DebugP_assert((object->operationType == AESCTR_OPERATION_TYPE_ENCRYPT_SEGMENTED) ||
777                   (object->operationType == AESCTR_OPERATION_TYPE_DECRYPT_SEGMENTED));
778 
779     /* Check for previous failure of segmented operation */
780     if (object->common.returnStatus != AESCTR_STATUS_SUCCESS)
781     {
782         /* Return the failure status of previous call.
783          * The callback will not be called.
784          */
785         return object->common.returnStatus;
786     }
787 
788 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 0)
789     /* Check word-alignment of input & output pointers */
790     if (!IS_WORD_ALIGNED(operation->input) || !IS_WORD_ALIGNED(operation->output))
791     {
792         return AESCTR_STATUS_UNALIGNED_IO_NOT_SUPPORTED;
793     }
794 #endif
795 
796     /* Check DMA xfer limit for blocking and callback modes */
797     if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) && (operation->inputLength > 0U) &&
798         !AESCommonLPF3_isDMALengthValid(operation->input, operation->output, operation->inputLength))
799     {
800         return AESCTR_STATUS_ERROR;
801     }
802 
803     /*
804      * Determine final operation type but do not save to object until
805      * we have obtained access to CRYPTO resource or there is no input
806      * to process. This allows app to retry finalization if the CRYPTO
807      * resource is unavailable.
808      */
809     if (object->operationType == AESCTR_OPERATION_TYPE_ENCRYPT_SEGMENTED)
810     {
811         operationType = AESCTR_OPERATION_TYPE_ENCRYPT_FINALIZE;
812     }
813     else
814     {
815         operationType = AESCTR_OPERATION_TYPE_DECRYPT_FINALIZE;
816     }
817 
818     if (operation->inputLength > 0U)
819     {
820         /* Try and obtain access to the crypto module */
821         if (object->threadSafe)
822         {
823             if (!CryptoResourceLPF3_acquireLock(object->common.semaphoreTimeout))
824             {
825                 return AESCTR_STATUS_RESOURCE_UNAVAILABLE;
826             }
827 
828             object->common.cryptoResourceLocked = true;
829         }
830 
831         object->operationType = operationType;
832         object->operation     = (AESCTR_OperationUnion *)operation;
833 
834         /* Make internal copy of operational params */
835         object->input                = operation->input;
836         object->inputLength          = operation->inputLength;
837         object->inputLengthRemaining = operation->inputLength;
838         object->output               = operation->output;
839 
840         status = AESCTRLPF3_startOperation(handle, true);
841     }
842     else /* Operation was finalized without additional data to process */
843     {
844         /*
845          * Save the object's returnStatus in case it is
846          * overwritten during setup of a new segmented operation
847          * after the operationInProgress flag is cleared.
848          */
849         status = object->common.returnStatus;
850 
851         AESCommonLPF3_clearOperationInProgress(&object->common);
852 
853         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
854         {
855             object->callbackFxn(handle, status, (AESCTR_OperationUnion *)operation, operationType);
856 
857             /* Always return success in callback mode */
858             status = AESCTR_STATUS_SUCCESS;
859         }
860     }
861 
862     return status;
863 }
864 
865 /*
866  *  ======== AESCTRLPF3_setupSegmentedOperation ========
867  */
AESCTRLPF3_setupSegmentedOperation(AESCTRLPF3_Object * object,const CryptoKey * key,const uint8_t initialCounter[AES_BLOCK_SIZE])868 static int_fast16_t AESCTRLPF3_setupSegmentedOperation(AESCTRLPF3_Object *object,
869                                                        const CryptoKey *key,
870                                                        const uint8_t initialCounter[AES_BLOCK_SIZE])
871 {
872     DebugP_assert(key);
873 
874     int_fast16_t status = AESCTR_STATUS_SUCCESS;
875 
876     /*
877      * Key material pointer and length are not checked until adding or
878      * finalizing data.
879      */
880     if (key->encoding == CryptoKey_PLAINTEXT)
881     {
882         /* When using the AES driver with the LAES engine */
883         status = AESCommonLPF3_setupSegmentedOperation(&object->common, key);
884     }
885 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
886     else if (key->encoding == CryptoKey_PLAINTEXT_HSM)
887     {
888         /* A segmented operation may have been started but not finalized yet */
889         if (object->segmentedOperationInProgress)
890         {
891             return AESCTR_STATUS_ERROR;
892         }
893 
894         /* Make internal copy of crypto key */
895         object->common.key = *key;
896 
897         /* returnStatus is only changed in the case of an error or cancellation */
898         object->common.returnStatus = AES_STATUS_SUCCESS;
899 
900         object->segmentedOperationInProgress = true;
901     }
902 #endif
903     else
904     {
905         status = AESCTR_STATUS_ERROR;
906     }
907 
908     if (status == AESCTR_STATUS_SUCCESS)
909     {
910         AESCTRLPF3_initCounter(object, &initialCounter[0]);
911 
912         /*
913          * Initialize operation pointer to NULL in case AESCTR_cancelOperation
914          * is called after AESCTR_setupXXXX and callback should be skipped.
915          */
916         object->operation = NULL;
917     }
918 
919     return status;
920 }
921 
922 /*
923  *  ======== AESCTR_setupEncrypt ========
924  */
AESCTR_setupEncrypt(AESCTR_Handle handle,const CryptoKey * key,const uint8_t * initialCounter)925 int_fast16_t AESCTR_setupEncrypt(AESCTR_Handle handle, const CryptoKey *key, const uint8_t *initialCounter)
926 {
927     DebugP_assert(handle);
928     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
929     DebugP_assert(object);
930 
931 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
932     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
933     if ((key->encoding == CryptoKey_PLAINTEXT_HSM) && (object->hsmStatus != HSMLPF3_STATUS_SUCCESS))
934     {
935         return AESCTR_STATUS_ERROR;
936     }
937 #endif
938 
939     int_fast16_t status = AESCTRLPF3_setupSegmentedOperation(object, key, initialCounter);
940 
941     if (status == AESCTR_STATUS_SUCCESS)
942     {
943         object->operationType = AESCTR_OPERATION_TYPE_ENCRYPT_SEGMENTED;
944     }
945 
946     return status;
947 }
948 
949 /*
950  *  ======== AESCTR_setupDecrypt ========
951  */
AESCTR_setupDecrypt(AESCTR_Handle handle,const CryptoKey * key,const uint8_t * initialCounter)952 int_fast16_t AESCTR_setupDecrypt(AESCTR_Handle handle, const CryptoKey *key, const uint8_t *initialCounter)
953 {
954     DebugP_assert(handle);
955     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
956     DebugP_assert(object);
957 
958 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
959     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
960     if ((key->encoding == CryptoKey_PLAINTEXT_HSM) && (object->hsmStatus != HSMLPF3_STATUS_SUCCESS))
961     {
962         return AESCTR_STATUS_ERROR;
963     }
964 #endif
965 
966     int_fast16_t status = AESCTRLPF3_setupSegmentedOperation(object, key, initialCounter);
967 
968     if (status == AESCTR_STATUS_SUCCESS)
969     {
970         object->operationType = AESCTR_OPERATION_TYPE_DECRYPT_SEGMENTED;
971     }
972 
973     return status;
974 }
975 
976 /*
977  *  ======== AESCTR_cancelOperation ========
978  */
AESCTR_cancelOperation(AESCTR_Handle handle)979 int_fast16_t AESCTR_cancelOperation(AESCTR_Handle handle)
980 {
981     DebugP_assert(handle);
982 
983     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
984 
985     uintptr_t interruptKey = HwiP_disable();
986 
987     /*
988      * Return success if there is no active operation to cancel.
989      * Do not execute the callback as it would have been executed already
990      * when the operation completed.
991      */
992 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
993     if (((object->common.key.encoding & CRYPTOKEY_HSM) == 0) && (!object->common.operationInProgress))
994 #else
995     if (!object->common.operationInProgress)
996 #endif
997     {
998         HwiP_restore(interruptKey);
999         return AESCTR_STATUS_SUCCESS;
1000     }
1001 
1002     HwiP_restore(interruptKey);
1003 
1004     /*
1005      * Cancel DMA for input and output channels, clear operation in-progress,
1006      * and releases crypto resource if necessary.
1007      */
1008     AESCommonLPF3_cancelOperation(&object->common, true);
1009 
1010 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1011     if ((object->common.key.encoding & CRYPTOKEY_HSM))
1012     {
1013         /* Since the HSM cannot cancel an in-progress token, we must wait for the result to allow for
1014          * subsequent token submissions to succeed.
1015          */
1016         (void)HSMLPF3_cancelOperation();
1017 
1018         object->segmentedOperationInProgress = false;
1019     }
1020 #endif
1021 
1022     /*
1023      * Operation pointer could be NULL if a segmented operation was setup
1024      * but neither AESCTR_addData or AESCTR_finalize was called.
1025      */
1026     if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK) && (object->operation != NULL))
1027     {
1028         /* Call the callback function provided by the application */
1029         object->callbackFxn(handle, AESCTR_STATUS_CANCELED, object->operation, object->operationType);
1030     }
1031 
1032     return AESCTR_STATUS_SUCCESS;
1033 }
1034 
1035 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1036 
1037 /*
1038  *  ======== AESCTRLPF3HSM_oneStepOperation ========
1039  */
AESCTRLPF3HSM_oneStepOperation(AESCTR_Handle handle,AESCTR_OneStepOperation * operation,AESCTR_OperationType operationType)1040 static int_fast16_t AESCTRLPF3HSM_oneStepOperation(AESCTR_Handle handle,
1041                                                    AESCTR_OneStepOperation *operation,
1042                                                    AESCTR_OperationType operationType)
1043 {
1044     DebugP_assert(handle);
1045     DebugP_assert(operation);
1046     DebugP_assert(operation->key);
1047     /* No need to assert operationType since we control it within the driver */
1048 
1049     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
1050 
1051     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
1052     if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
1053     {
1054         return AESCTR_STATUS_ERROR;
1055     }
1056 
1057     /* Verify input length is non-zero */
1058     if (operation->inputLength == 0U)
1059     {
1060         return AESCTR_STATUS_ERROR;
1061     }
1062 
1063     /* A segmented operation may have been started but not finalized yet */
1064     if (object->segmentedOperationInProgress)
1065     {
1066         return AESCTR_STATUS_ERROR;
1067     }
1068 
1069     object->operation           = (AESCTR_OperationUnion *)operation;
1070     object->operationType       = operationType;
1071     /* We will only change the returnStatus if there is an error or cancellation */
1072     object->common.returnStatus = AESCTR_STATUS_SUCCESS;
1073 
1074     /* Make internal copy of operational params */
1075     object->common.key = *(operation->key);
1076 
1077     object->input       = operation->input;
1078     object->output      = operation->output;
1079     object->inputLength = operation->inputLength;
1080 
1081     AESCTRLPF3_initCounter(object, &operation->initialCounter[0]);
1082 
1083     return AESCTRLPF3HSM_processOneStepOperation(handle);
1084 }
1085 
1086 /*
1087  *  ======== AESCTRLPF3HSM_OneStepOperationPostProcessing ========
1088  */
AESCTRLPF3HSM_OneStepOperationPostProcessing(uintptr_t arg0)1089 static inline void AESCTRLPF3HSM_OneStepOperationPostProcessing(uintptr_t arg0)
1090 {
1091     AESCTR_Handle handle      = (AESCTR_Handle)arg0;
1092     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
1093     int_fast16_t status       = AESCTR_STATUS_ERROR;
1094     int32_t physicalResult    = HSMLPF3_getResultCode();
1095     int32_t tokenResult       = physicalResult & HSMLPF3_RETVAL_MASK;
1096 
1097     if (tokenResult == EIP130TOKEN_RESULT_SUCCESS)
1098     {
1099         status = AESCTR_STATUS_SUCCESS;
1100 
1101         HSMLPF3_getAESIV((void *)&object->counter[0]);
1102     }
1103 
1104     object->common.returnStatus = status;
1105 
1106     HSMLPF3_releaseLock();
1107 
1108     Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
1109 
1110     if ((object->operationType == AESCTR_OPERATION_TYPE_ENCRYPT_FINALIZE) ||
1111         (object->operationType == AESCTR_OPERATION_TYPE_DECRYPT_FINALIZE) ||
1112         (object->operationType == AESCTR_OPERATION_TYPE_ENCRYPT) ||
1113         (object->operationType == AESCTR_OPERATION_TYPE_DECRYPT))
1114     {
1115         object->segmentedOperationInProgress = false;
1116     }
1117 
1118     if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
1119     {
1120         object->callbackFxn(handle, object->common.returnStatus, object->operation, object->operationType);
1121     }
1122 }
1123 
1124 /*
1125  *  ======== AESCTRLPF3HSM_processOneStepOperation ========
1126  */
AESCTRLPF3HSM_processOneStepOperation(AESCTR_Handle handle)1127 static int_fast16_t AESCTRLPF3HSM_processOneStepOperation(AESCTR_Handle handle)
1128 {
1129     int_fast16_t status       = AESCTR_STATUS_ERROR;
1130     int_fast16_t hsmRetval    = HSMLPF3_STATUS_ERROR;
1131     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
1132 
1133     if (!HSMLPF3_acquireLock(SemaphoreP_NO_WAIT, (uintptr_t)handle))
1134     {
1135         return AESCTR_STATUS_RESOURCE_UNAVAILABLE;
1136     }
1137 
1138     Power_setConstraint(PowerLPF3_DISALLOW_STANDBY);
1139 
1140     HSMLPF3_constructAESCTROneStepPhysicalToken(object);
1141 
1142     hsmRetval = HSMLPF3_submitToken((HSMLPF3_ReturnBehavior)object->common.returnBehavior,
1143                                     AESCTRLPF3HSM_OneStepOperationPostProcessing,
1144                                     (uintptr_t)handle);
1145     if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
1146     {
1147         hsmRetval = HSMLPF3_waitForResult();
1148 
1149         if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
1150         {
1151             status = object->common.returnStatus;
1152         }
1153     }
1154 
1155     if (hsmRetval != HSMLPF3_STATUS_SUCCESS)
1156     {
1157         Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
1158 
1159         HSMLPF3_releaseLock();
1160     }
1161 
1162     return status;
1163 }
1164 
AESCTRLPF3HSM_addData(AESCTR_Handle handle,AESCTR_SegmentedOperation * operation)1165 int_fast16_t AESCTRLPF3HSM_addData(AESCTR_Handle handle, AESCTR_SegmentedOperation *operation)
1166 {
1167     DebugP_assert(handle);
1168     DebugP_assert(operation);
1169 
1170     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
1171 
1172     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
1173     if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
1174     {
1175         return AESCTR_STATUS_ERROR;
1176     }
1177 
1178     /* Assert the segmented operation was setup */
1179     DebugP_assert((object->operationType == AESCTR_OPERATION_TYPE_ENCRYPT_SEGMENTED) ||
1180                   (object->operationType == AESCTR_OPERATION_TYPE_DECRYPT_SEGMENTED));
1181 
1182     /* Check for previous failure or cancellation of segmented operation */
1183     if (object->common.returnStatus != AESCTR_STATUS_SUCCESS)
1184     {
1185         /*
1186          * Return the status of the previous call.
1187          * The callback function will not be executed.
1188          */
1189         return object->common.returnStatus;
1190     }
1191 
1192     /* Verify the input length is non-zero and a multiple of the block size */
1193     if ((operation->inputLength == 0U) || ((operation->inputLength & AES_NON_BLOCK_SIZE_MULTIPLE_MASK) != 0U))
1194     {
1195         return AESCTR_STATUS_ERROR;
1196     }
1197 
1198     object->operation = (AESCTR_OperationUnion *)operation;
1199 
1200     object->input       = operation->input;
1201     object->output      = operation->output;
1202     object->inputLength = operation->inputLength;
1203 
1204     return AESCTRLPF3HSM_processOneStepOperation(handle);
1205 }
1206 
AESCTRLPF3HSM_finalize(AESCTR_Handle handle,AESCTR_SegmentedOperation * operation)1207 int_fast16_t AESCTRLPF3HSM_finalize(AESCTR_Handle handle, AESCTR_SegmentedOperation *operation)
1208 {
1209     DebugP_assert(handle);
1210     DebugP_assert(operation);
1211 
1212     AESCTRLPF3_Object *object = AESCTRLPF3_getObject(handle);
1213     AESCTR_OperationType operationType;
1214     int_fast16_t status;
1215 
1216     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
1217     if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
1218     {
1219         return AESCTR_STATUS_ERROR;
1220     }
1221 
1222     /* Assert the segmented operation was setup */
1223     DebugP_assert((object->operationType == AESCTR_OPERATION_TYPE_ENCRYPT_SEGMENTED) ||
1224                   (object->operationType == AESCTR_OPERATION_TYPE_DECRYPT_SEGMENTED));
1225 
1226     /* Check for previous failure of segmented operation */
1227     if (object->common.returnStatus != AESCTR_STATUS_SUCCESS)
1228     {
1229         /* Return the failure status of previous call.
1230          * The callback will not be called.
1231          */
1232         return object->common.returnStatus;
1233     }
1234 
1235     if (object->operationType == AESCTR_OPERATION_TYPE_ENCRYPT_SEGMENTED)
1236     {
1237         operationType = AESCTR_OPERATION_TYPE_ENCRYPT_FINALIZE;
1238     }
1239     else
1240     {
1241         operationType = AESCTR_OPERATION_TYPE_DECRYPT_FINALIZE;
1242     }
1243 
1244     if (operation->inputLength > 0U)
1245     {
1246         object->operationType = operationType;
1247         object->operation     = (AESCTR_OperationUnion *)operation;
1248 
1249         object->input       = operation->input;
1250         object->output      = operation->output;
1251         object->inputLength = operation->inputLength;
1252 
1253         status = AESCTRLPF3HSM_processOneStepOperation(handle);
1254     }
1255     else /* Operation was finalized without additional data to process */
1256     {
1257         /* Save the object's returnStatus in case it is
1258          * overwritten during setup of a new segmented operation
1259          * after the operationInProgress flag is cleared.
1260          */
1261         status = object->common.returnStatus;
1262 
1263         object->segmentedOperationInProgress = false;
1264 
1265         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
1266         {
1267             object->callbackFxn(handle, status, (AESCTR_OperationUnion *)operation, operationType);
1268 
1269             /* Always return success in callback mode */
1270             status = AESCTR_STATUS_SUCCESS;
1271         }
1272     }
1273 
1274     return status;
1275 }
1276 
1277 #endif
1278