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/aesccm/AESCCMLPF3.h>
38 #include <ti/drivers/AESCCM.h>
39 #include <ti/drivers/aescmac/AESCMACLPF3.h>
40 #include <ti/drivers/AESCommon.h>
41 #include <ti/drivers/aesctr/AESCTRLPF3.h>
42 #include <ti/drivers/cryptoutils/aes/AESCommonLPF3.h>
43 #include <ti/drivers/cryptoutils/cryptokey/CryptoKey.h>
44 #include <ti/drivers/cryptoutils/sharedresources/CryptoResourceLPF3.h>
45 #include <ti/drivers/cryptoutils/utils/CryptoUtils.h>
46 #include <ti/drivers/dma/UDMALPF3.h>
47 
48 #include <ti/drivers/dpl/DebugP.h>
49 #include <ti/drivers/dpl/HwiP.h>
50 #include <ti/drivers/dpl/SemaphoreP.h>
51 
52 #include <ti/devices/DeviceFamily.h>
53 #include DeviceFamily_constructPath(driverlib/aes.h)
54 #include DeviceFamily_constructPath(inc/hw_aes.h)
55 #include DeviceFamily_constructPath(inc/hw_ints.h)
56 
57 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
58     #include <ti/drivers/cryptoutils/hsm/HSMLPF3.h>
59     #include <third_party/hsmddk/include/Integration/Adapter_VEX/incl/adapter_vex.h>
60     #include <third_party/hsmddk/include/Integration/Adapter_PSA/incl/adapter_psa_asset.h>
61 #endif
62 
63 #if (defined(__IAR_SYSTEMS_ICC__) || defined(__TI_COMPILER_VERSION__))
64     #include <arm_acle.h>
65     #define REV32 __rev
66 #else
67     #define REV32 __builtin_bswap32
68 #endif
69 
70 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
71     #define PSA_SYM_MODE_GCM_NONE 0U
72 
73     /* Size of state asset for GCM/CCM continuation */
74     #define KEY_TEMP_ASSET_SIZE 48U
75 #endif
76 
77 /* Note: The AES-CCM one-step polling operations are specifically designed
78  * to optimize execution speed at the expense of code re-use and size.
79  */
80 
81 #define B0_FLAGS_CCM_HAS_ADATA 0x40 /* bit 6 in the Flags field of B0 */
82 
83 /**
84  * This AES CCM implementation limits AAD length to 0xFEFF (65279-bytes) to
85  * simplify the code and improve execution speed.
86  */
87 /* 0xFEFF bytes, For 0 < l(a) <= (2^16 - 2^8) - 1 */
88 #define B1_AAD_LENGTH_SMALL_LIMIT ((1UL << 16) - (1UL << 8) - 1UL)
89 
90 #define B1_AAD_LENGTH_SMALL_BYTES 2U /* If 0 < l(a) < (2^16 - 2^8), the length field is encoded as two octets */
91 #define B1_AAD_SMALL_BYTES        (AES_BLOCK_SIZE - B1_AAD_LENGTH_SMALL_BYTES)
92 
93 /**
94  * The threshold at which blocking and callback mode transfers will utilize DMA.
95  * For data lengths below this threshold, polling CPU R/W will be used instead
96  * of DMA. With task switching and interrupt overhead, it is inefficient to
97  * utilize DMA for shorter length operations.
98  * The threshold value must be a multiple of AES_BLOCK_SIZE.
99  */
100 #define AESCCMLPF3_DMA_SIZE_THRESHOLD (1U * AES_BLOCK_SIZE)
101 
102 /* Forward declarations */
103 static int_fast16_t AESCCMLPF3_addData(AESCCM_Handle handle,
104                                        AESCCM_OperationType operationType,
105                                        AESCCM_OperationUnion *operation,
106                                        const uint8_t *input,
107                                        uint8_t *output,
108                                        size_t inputLength);
109 static int_fast16_t AESCCMLPF3_addDataDMA(AESCCM_Handle handle, AESCCM_Mode direction, size_t inputLength);
110 static inline int_fast16_t AESCCMLPF3_finishTag(AESCCMLPF3_Object *object, AESCCM_Mode direction);
111 static int_fast16_t AESCCMLPF3_oneStepOperation(AESCCM_Handle handle,
112                                                 AESCCM_OneStepOperation *operation,
113                                                 AESCCM_OperationType operationType);
114 static int_fast16_t AESCCMLPF3_performFinalizeChecks(const AESCCMLPF3_Object *object,
115                                                      const AESCCM_SegmentedFinalizeOperation *operation);
116 static void AESCCMLPF3_processB0(const uint8_t *nonce,
117                                  uint8_t nonceLength,
118                                  size_t totalAADLength,
119                                  size_t totalDataLength,
120                                  uint8_t macLength);
121 static size_t AESCCMLPF3_processB1withAAD(const uint8_t *aad, size_t aadSegmentLength, size_t aadTotalLength);
122 static void AESCCMLPF3_processOneStepCBCMACPolling(AESCCM_OneStepOperation *operation,
123                                                    uint32_t tag[AES_TAG_LENGTH_BYTES / 4U],
124                                                    AESCCM_Mode direction);
125 static void AESCCMLPF3_processOneStepCTRPolling(AESCCM_OneStepOperation *operation,
126                                                 uint32_t tag[AES_TAG_LENGTH_BYTES / 4U]);
127 static inline int_fast16_t AESCCMLPF3_processOneStepDecryptPolling(AESCCMLPF3_Object *object,
128                                                                    AESCCM_OneStepOperation *operation);
129 static inline int_fast16_t AESCCMLPF3_processOneStepEncryptPolling(AESCCMLPF3_Object *object,
130                                                                    AESCCM_OneStepOperation *operation);
131 static int_fast16_t AESCCMLPF3_setupSegmentedOperation(AESCCMLPF3_Object *object,
132                                                        const CryptoKey *key,
133                                                        size_t totalAADLength,
134                                                        size_t totalDataLength,
135                                                        size_t macLength);
136 static void AESCCMLPF3_processCBCMACFinalBlock(const uint8_t *input, size_t bytesRemaining);
137 static void AESCCMLPF3_processCTRCounterBlock(const uint8_t *nonce, uint8_t nonceLength, uint8_t counterVal);
138 static int_fast16_t AESCCMLPF3_processSegmentedCBCMAC(AESCCMLPF3_Object *object,
139                                                       size_t aadSegmentLength,
140                                                       size_t dataSegmentLength,
141                                                       AESCCM_Mode direction);
142 static int_fast16_t AESCCMLPF3_processSegmentedCTR(AESCCMLPF3_Object *object, size_t dataSegmentLength);
143 static void AESCCMLPF3_processTagCTR(AESCCMLPF3_Object *object);
144 static int_fast16_t AESCCMLPF3_waitForDMA(const AESCCMLPF3_Object *object);
145 
146 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
147 static int_fast16_t AESCCMLPF3HSM_setupEncrypt(AESCCM_Handle handle,
148                                                const CryptoKey *key,
149                                                size_t totalAADLength,
150                                                size_t totalPlaintextLength,
151                                                size_t macLength);
152 static int_fast16_t AESCCMLPF3HSM_setupDecrypt(AESCCM_Handle handle,
153                                                const CryptoKey *key,
154                                                size_t totalAADLength,
155                                                size_t totalPlaintextLength,
156                                                size_t macLength);
157 static int_fast16_t AESCCMLPF3HSM_addAAD(AESCCM_Handle handle, AESCCM_SegmentedAADOperation *operation);
158 static int_fast16_t AESCCMLPF3HSM_addData(AESCCM_Handle handle,
159                                           AESCCM_OperationType operationType,
160                                           AESCCM_OperationUnion *operation,
161                                           const uint8_t *input,
162                                           uint8_t *output,
163                                           size_t inputLength);
164 static int_fast16_t AESCCMLPF3HSM_finalizeEncrypt(AESCCM_Handle handle, AESCCM_SegmentedFinalizeOperation *operation);
165 static int_fast16_t AESCCMLPF3HSM_finalizeDecrypt(AESCCM_Handle handle, AESCCM_SegmentedFinalizeOperation *operation);
166 static int_fast16_t AESCCMLPF3HSM_oneStepOperation(AESCCM_Handle handle,
167                                                    AESCCM_OneStepOperation *operation,
168                                                    AESCCM_OperationType operationType);
169 static int_fast16_t AESCCMLPF3HSM_performFinalizeChecks(const AESCCMLPF3_Object *object,
170                                                         const AESCCM_SegmentedFinalizeOperation *operation);
171 static int_fast16_t AESCCMLPF3HSM_setupSegmentedOperation(AESCCMLPF3_Object *object,
172                                                           const CryptoKey *key,
173                                                           size_t totalAADLength,
174                                                           size_t totalDataLength,
175                                                           size_t macLength);
176 static int_fast16_t AESCCMLPF3HSM_createTempAssetID(AESCCM_Handle handle, AESCCM_Mode direction);
177 static inline int_fast16_t AESCCMLPF3HSM_processOneStepOperation(AESCCM_Handle handle);
178 static int_fast16_t AESCCMLPF3HSM_freeTempAssetID(AESCCM_Handle handle);
179 #endif
180 
181 /*
182  *  ======== AESCCMLPF3_getObject ========
183  */
AESCCMLPF3_getObject(AESCCM_Handle handle)184 static inline AESCCMLPF3_Object *AESCCMLPF3_getObject(AESCCM_Handle handle)
185 {
186     AESCCMLPF3_Object *object = (AESCCMLPF3_Object *)handle->object;
187     DebugP_assert(object);
188 
189     return object;
190 }
191 
192 /*
193  *  ======== AESCCMLPF3_hwiFxn ========
194  *
195  * Note: In order to support callback return behavior, there is an undesireable
196  * amount of processing done within this ISR. If support for callback return
197  * behavior can be removed in the future, this processing should be moved to
198  * the thread context to improve IRQ responsiveness.
199  */
AESCCMLPF3_hwiFxn(uintptr_t arg0)200 static void AESCCMLPF3_hwiFxn(uintptr_t arg0)
201 {
202     bool isOpDone             = false;
203     AESCCM_Handle handle      = (AESCCM_Handle)arg0;
204     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
205 
206     /* For CBC-MAC, only the input channel A interrupt is enabled.
207      * For CTR, only the output channel B interrupt is enabled.
208      */
209     uint32_t intStatus = AESGetMaskedInterruptStatus();
210 
211     /* Disable DMA, clear interupts, and release power constraint */
212     AESCommonLPF3_cleanupHwi(&object->common);
213 
214     AESCCM_Mode direction = AESCCM_MODE_ENCRYPT;
215 
216     if ((object->operationType == AESCCM_OP_TYPE_ONESTEP_DECRYPT) ||
217         (object->operationType == AESCCM_OP_TYPE_DATA_DECRYPT) ||
218         (object->operationType == AESCCM_OP_TYPE_FINALIZE_DECRYPT))
219     {
220         direction = AESCCM_MODE_DECRYPT;
221     }
222 
223     if ((intStatus & (uint32_t)AES_MIS_CHADONE_M) != (uint32_t)0U)
224     {
225         UDMALPF3_clearInterrupt(AESCommonLPF3_DMA_CHA_BITMASK);
226 
227         const uint8_t *plainText = object->input;
228         if (direction == AESCCM_MODE_DECRYPT)
229         {
230             plainText = object->output;
231         }
232 
233         /* DMA is used to process full blocks of data but there if there is a
234          * partial block of data remaining, handle it with CPU R/W.
235          */
236         if (object->inputCBCMACLengthRemaining > 0U)
237         {
238             size_t inputCBCMACLengthRemaining = object->inputCBCMACLengthRemaining;
239             /* Use CPU R/W to complete the CBC-MAC operation */
240             AESCCMLPF3_processCBCMACFinalBlock(&plainText[object->inputLength - inputCBCMACLengthRemaining],
241                                                inputCBCMACLengthRemaining);
242 
243             object->totalCBCMACLengthRemaining -= inputCBCMACLengthRemaining;
244             object->inputCBCMACLengthRemaining = 0U;
245         }
246 
247         /* Wait for operation to complete and save the intermediate tag */
248         AESCMACLPF3_readTag((uint32_t *)&object->intermediateTag[0]);
249 
250         if (object->totalCBCMACLengthRemaining == 0U)
251         {
252             object->common.returnStatus = AESCCMLPF3_finishTag(object, direction);
253         }
254 
255         if (direction == AESCCM_MODE_DECRYPT)
256         {
257             isOpDone = true;
258         }
259         else /* Encrypt */
260         {
261             object->common.returnStatus = AESCCMLPF3_processSegmentedCTR(object, object->inputLength);
262 
263             /* Operation will be handled without DMA if length less than threshold */
264             if (object->inputLength < AESCCMLPF3_DMA_SIZE_THRESHOLD)
265             {
266                 isOpDone = true;
267             }
268         }
269     }
270 
271     if ((intStatus & (uint32_t)AES_MIS_CHBDONE_M) != (uint32_t)0U)
272     {
273         UDMALPF3_clearInterrupt(AESCommonLPF3_DMA_CHB_BITMASK);
274 
275         /* DMA is used to process all full blocks of data. If there is a
276          * partial block of data remaining, process it with CPU R/W.
277          */
278         if (object->inputCTRLengthRemaining > 0U)
279         {
280             size_t inputCTRLengthRemaining = object->inputCTRLengthRemaining;
281             /* Use CPU R/W to complete the CTR operation */
282             AESCTRLPF3_processData(&object->input[object->inputLength - inputCTRLengthRemaining],
283                                    &object->output[object->inputLength - inputCTRLengthRemaining],
284                                    inputCTRLengthRemaining,
285                                    true);
286 
287             object->totalCTRLengthRemaining -= inputCTRLengthRemaining;
288             object->inputCTRLengthRemaining = 0U;
289         }
290 
291         if (object->totalCTRLengthRemaining > 0U)
292         {
293             /* Store the counter if more input data is expected */
294             AESCTRLPF3_readCounter((uint32_t *)&object->intermediateCounter[0]);
295         }
296 
297         if (direction == AESCCM_MODE_ENCRYPT)
298         {
299             isOpDone = true;
300         }
301         else /* Decrypt */
302         {
303             object->common.returnStatus = AESCCMLPF3_processSegmentedCBCMAC(object,
304                                                                             0U,
305                                                                             object->inputLength,
306                                                                             AESCCM_MODE_DECRYPT);
307 
308             /* Operation is completed without DMA if length < threshold */
309             if (object->inputLength < AESCCMLPF3_DMA_SIZE_THRESHOLD)
310             {
311                 isOpDone = true;
312             }
313         }
314     }
315 
316     if (isOpDone)
317     {
318         /* Store sum of AES lengths in a temporary variable to explicitly
319          * define access order since both fields are volatile.
320          */
321         size_t totalLengthRemaining = object->totalCTRLengthRemaining;
322         totalLengthRemaining += object->totalCBCMACLengthRemaining;
323 
324         if (totalLengthRemaining == 0U)
325         {
326             AESCommonLPF3_clearOperationInProgress(&object->common);
327         }
328 
329         /* Cleanup and release crypto resource lock */
330         AESCommonLPF3_cleanup(&object->common);
331 
332         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_BLOCKING)
333         {
334             /* Unblock the pending task to signal that the operation is complete */
335             SemaphoreP_post(&CryptoResourceLPF3_operationSemaphore);
336         }
337         else
338         {
339             /* Call the callback function provided by the application */
340             object->callbackFxn(handle, object->common.returnStatus, object->operation, object->operationType);
341         }
342     }
343 }
344 
345 /*
346  *  ======== AESCCMLPF3_finishTag ========
347  */
AESCCMLPF3_finishTag(AESCCMLPF3_Object * object,AESCCM_Mode direction)348 static inline int_fast16_t AESCCMLPF3_finishTag(AESCCMLPF3_Object *object, AESCCM_Mode direction)
349 {
350     int_fast16_t status = AESCCM_STATUS_SUCCESS;
351 
352     AESCCMLPF3_processTagCTR(object);
353 
354     if (object->mac != NULL)
355     {
356         if (direction == AESCCM_MODE_ENCRYPT)
357         {
358             (void)memcpy((void *)&object->mac[0], (void *)&object->intermediateTag[0], object->macLength);
359         }
360         else /* Decrypt */
361         {
362             /* Perform a constant time comparison of the calculated MAC and the decrypted MAC */
363             bool macValid = CryptoUtils_buffersMatch(object->intermediateTag, object->mac, (size_t)object->macLength);
364 
365             if (!macValid)
366             {
367                 status = AESCCM_STATUS_MAC_INVALID;
368             }
369         }
370     }
371 
372     return status;
373 }
374 
375 /*
376  *  ======== AESCCMLPF3_waitForDMA ========
377  */
AESCCMLPF3_waitForDMA(const AESCCMLPF3_Object * object)378 static int_fast16_t AESCCMLPF3_waitForDMA(const AESCCMLPF3_Object *object)
379 {
380     int_fast16_t status;
381 
382     if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_BLOCKING)
383     {
384         /* This function may be called from handler or thread contexts.
385          * Only block on semaphore when called from thread context
386          * (i.e. Interrupt Program Status Register is zero)
387          */
388         if ((uint32_t)__get_IPSR() == (uint32_t)0U)
389         {
390             /* Ignore return value since timeout is infinite */
391             (void)SemaphoreP_pend((SemaphoreP_Handle)&CryptoResourceLPF3_operationSemaphore,
392                                   (uint32_t)SemaphoreP_WAIT_FOREVER);
393         }
394 
395         /* Return status stored in ISR */
396         status = object->common.returnStatus;
397     }
398     else /* AES_RETURN_BEHAVIOR_CALLBACK */
399     {
400         /* Success is always returned in callback mode */
401         status = AESCCM_STATUS_SUCCESS;
402     }
403 
404     return status;
405 }
406 
407 /*
408  *  ======== AESCCM_init ========
409  */
AESCCM_init(void)410 void AESCCM_init(void)
411 {
412 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
413     HSMLPF3_constructRTOSObjects();
414 #endif
415     AESCommonLPF3_init();
416 }
417 
418 /*
419  *  ======== AESCCM_construct ========
420  */
AESCCM_construct(AESCCM_Config * config,const AESCCM_Params * params)421 AESCCM_Handle AESCCM_construct(AESCCM_Config *config, const AESCCM_Params *params)
422 {
423     DebugP_assert(config);
424 
425     int_fast16_t status;
426     AESCCM_Handle handle      = config;
427     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
428 
429 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
430     /* Initialize and boot HSM */
431     if (HSMLPF3_init() != HSMLPF3_STATUS_SUCCESS)
432     {
433         /* Upon HSM Boot failure, the AES-CCM Driver stores the failure status in the object
434          * This is done so that users of the AES-CCM Driver do not get a NULL handle and still can use
435          * the driver in LAES mode.
436          */
437         object->hsmStatus = HSMLPF3_STATUS_ERROR;
438     }
439     else
440     {
441         object->hsmStatus = HSMLPF3_STATUS_SUCCESS;
442 
443         object->segmentedOperationInProgress = false;
444     }
445 #endif
446 
447     /* If params are NULL, use defaults */
448     if (params == NULL)
449     {
450         params = &AESCCM_defaultParams;
451     }
452 
453     DebugP_assert((params->returnBehavior != AESCCM_RETURN_BEHAVIOR_CALLBACK) || (params->callbackFxn != NULL));
454 
455     object->callbackFxn = params->callbackFxn;
456 
457     status = AESCommonLPF3_construct(&object->common, (AES_ReturnBehavior)params->returnBehavior, params->timeout);
458 
459     if (status != AES_STATUS_SUCCESS)
460     {
461         handle = NULL;
462     }
463 
464     return handle;
465 }
466 
467 /*
468  *  ======== AESCCM_close ========
469  */
AESCCM_close(AESCCM_Handle handle)470 void AESCCM_close(AESCCM_Handle handle)
471 {
472     DebugP_assert(handle);
473 
474     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
475 
476     AESCommonLPF3_close(&object->common);
477 }
478 
479 /*
480  *  ======== AESCCMLPF3_processCBCMACFinalBlock ========
481  */
AESCCMLPF3_processCBCMACFinalBlock(const uint8_t * input,size_t bytesRemaining)482 static void AESCCMLPF3_processCBCMACFinalBlock(const uint8_t *input, size_t bytesRemaining)
483 {
484     /* No need to reload the last intermediate tag because it still loaded in
485      * the AES engine from the previous CBCMAC operation.
486      */
487 
488     /* Must wait until engine is idle before clearing BUF */
489     while (AESGetStatus() != (uint32_t)AES_STA_STATE_IDLE) {}
490 
491     /* Zero out the BUF registers */
492     AESClearBUF();
493 
494     /* Copy directly to BUF registers. (void)memcpy is safe to use here since the
495      * order of the writes is not important when writing a partial block.
496      */
497     (void)memcpy((void *)(AES_BASE + AES_O_BUF0), input, bytesRemaining);
498 
499 #if DeviceFamily_PARENT == DeviceFamily_PARENT_CC23X0
500     AESSetTrigger((uint32_t)AES_TRG_AESOP_TXTXBUF);
501 #elif DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX
502     AESSetTrigger((uint32_t)AES_TRG_ECBOP_TXTXBUF);
503 #else
504     #error "Unsupported DeviceFamily_Parent for AESCMACLPF3!"
505 #endif
506 }
507 
508 #define M_PRIME_OFFSET 3
509 
510 /*
511  *  ======== AESCCMLPF3_processB0 ========
512  */
513 #if defined(__IAR_SYSTEMS_ICC__)
514     #pragma inline = forced
515 #elif defined(__TI_COMPILER_VERSION__)
516     #pragma FUNC_ALWAYS_INLINE(AESCCMLPF3_processB0)
517 #else
518 __attribute__((always_inline)) inline
519 #endif
AESCCMLPF3_processB0(const uint8_t * nonce,uint8_t nonceLength,size_t totalAADLength,size_t totalDataLength,uint8_t macLength)520 static void AESCCMLPF3_processB0(const uint8_t *nonce,
521                                  uint8_t nonceLength,
522                                  size_t totalAADLength,
523                                  size_t totalDataLength,
524                                  uint8_t macLength)
525 {
526     AES_BlockWordAligned B0;
527 
528     /* ============================================
529      * First block B0 formatting per RFC3610:
530      *    Octet Number   Contents
531      *    ------------   ---------
532      *    0              Flags
533      *    1 ... 15-L     Nonce N
534      *    16-L ... 15    l(m)
535      *
536      * Flags in octet 0 of B0:
537      *    Bit Number   Contents
538      *    ----------   ----------------------
539      *    7            Reserved (always zero)
540      *    6            Adata
541      *    5 ... 3      M'
542      *    2 ... 0      L'
543      * ============================================
544      */
545 
546     /* Set L'
547      *   nonceLength = 15 - L
548      *   L' = L - 1
549      *   L' = 15 - nonceLength - 1
550      *   L' = 14 - nonceLength
551      */
552     B0.words[0] = (uint32_t)14U - (uint32_t)nonceLength;
553 
554     /* Set M'
555      *   M' = (M - 2) / 2 where M = length of MAC
556      */
557     B0.words[0] |= (((uint32_t)macLength - (uint32_t)2U) >> 1) << M_PRIME_OFFSET;
558 
559     if (totalAADLength != 0U)
560     {
561         /* Set bit 6 (Adata) */
562         B0.words[0] |= (uint32_t)B0_FLAGS_CCM_HAS_ADATA;
563     }
564 
565     /* Set l(m), the length of the message, in most-significant-byte first order.
566      *
567      * Do this before copying nonce so word-based write can be utilized and then
568      * nonce's byte-wise copy will overwrite parts of the word not used for l(m).
569      */
570     B0.words[3] = REV32(totalDataLength);
571 
572     /* Copy nonce into B0, clearing bytes first to ensure uncopied bytes are zero. */
573     B0.words[1] = (uint32_t)0U;
574     B0.words[2] = (uint32_t)0U;
575 
576     (void)memcpy(&B0.bytes[1], nonce, nonceLength);
577 
578     AESWriteBUF32(B0.words);
579 }
580 
581 /*
582  *  ======== AESCCMLPF3_processB1withAAD ========
583  */
AESCCMLPF3_processB1withAAD(const uint8_t * aad,size_t aadSegmentLength,size_t aadTotalLength)584 static size_t AESCCMLPF3_processB1withAAD(const uint8_t *aad, size_t aadSegmentLength, size_t aadTotalLength)
585 {
586     size_t aadBytesProcessed = aadSegmentLength;
587     AES_BlockWordAligned B1;
588 
589     B1.words[0] = (uint32_t)0U;
590     B1.words[1] = (uint32_t)0U;
591     B1.words[2] = (uint32_t)0U;
592     B1.words[3] = (uint32_t)0U;
593 
594     /* Per RFC3610: If 0 < l(a) < (2^16 - 2^8), then the length field
595      * is encoded as two octets which contain the value l(a) in
596      * most-significant-byte first order.
597      *
598      * Note: Accessing via byte ptr is 5-cycles faster than using bit shift
599      * and masking.
600      */
601     uint8_t *aadLengthBytePtr = (uint8_t *)&aadTotalLength;
602     B1.bytes[1]               = *(aadLengthBytePtr);
603     B1.bytes[0]               = *(aadLengthBytePtr + 1U);
604 
605     /* Append the remaining AAD bytes */
606     if (aadSegmentLength == 1U)
607     {
608         /* Optimization for BLE stack use case which has 1-byte AAD */
609         B1.bytes[2] = aad[0];
610     }
611     else if (aadSegmentLength <= B1_AAD_SMALL_BYTES)
612     {
613         (void)memcpy((void *)&B1.bytes[2], (void *)aad, aadSegmentLength);
614     }
615     else
616     {
617         (void)memcpy((void *)&B1.bytes[2], (void *)aad, B1_AAD_SMALL_BYTES);
618         aadBytesProcessed = B1_AAD_SMALL_BYTES;
619     }
620 
621     /* B1 can be written to BUF while AES engine is still processing B0 */
622     AESWriteBUF32(B1.words);
623 
624     return aadBytesProcessed;
625 }
626 
627 /*
628  *  ======== AESCCMLPF3_processCBCMACPolling ========
629  */
AESCCMLPF3_processOneStepCBCMACPolling(AESCCM_OneStepOperation * operation,uint32_t tag[AES_TAG_LENGTH_BYTES/4U],AESCCM_Mode direction)630 static void AESCCMLPF3_processOneStepCBCMACPolling(AESCCM_OneStepOperation *operation,
631                                                    uint32_t tag[AES_TAG_LENGTH_BYTES / 4U],
632                                                    AESCCM_Mode direction)
633 {
634     size_t dataBytesRemaining;
635     size_t aadBytesRemaining;
636 
637     AESSetAUTOCFG(AESCMACLPF3_DEFAULT_AUTOCFG);
638 
639     /* Set IV to zero */
640     AESClearIV();
641 
642     AESCCMLPF3_processB0(operation->nonce,
643                          operation->nonceLength,
644                          operation->aadLength,
645                          operation->inputLength,
646                          operation->macLength);
647 
648     /* Process AAD */
649     if (operation->aadLength > 0U)
650     {
651         aadBytesRemaining = operation->aadLength;
652 
653         /* Process B1 with AAD */
654         aadBytesRemaining -= AESCCMLPF3_processB1withAAD(operation->aad, operation->aadLength, operation->aadLength);
655 
656         /* Process any remaining AAD */
657         if (aadBytesRemaining > 0U)
658         {
659             size_t blockSizeAlignedAADLength = AES_BLOCK_SIZE_MULTIPLE_LENGTH(aadBytesRemaining);
660 
661             if (blockSizeAlignedAADLength > 0U)
662             {
663                 AESCMACLPF3_processBlocks(&operation->aad[operation->aadLength - aadBytesRemaining],
664                                           blockSizeAlignedAADLength);
665 
666                 aadBytesRemaining -= blockSizeAlignedAADLength;
667             }
668 
669             if (aadBytesRemaining > 0U)
670             {
671                 AESCCMLPF3_processCBCMACFinalBlock(&operation->aad[operation->aadLength - aadBytesRemaining],
672                                                    aadBytesRemaining);
673             }
674         }
675     }
676 
677     dataBytesRemaining = operation->inputLength;
678 
679     if (dataBytesRemaining > 0U)
680     {
681         /* Perform CBCMAC on plaintext data, that is, depending on encryption/decryption,
682          * use input/output data respectively.
683          */
684 
685         uint8_t *plainText = operation->input;
686         if (direction != AESCCM_MODE_ENCRYPT)
687         {
688             plainText = operation->output;
689         }
690 
691         size_t blockSizeAlignedDataRemaining = AES_BLOCK_SIZE_MULTIPLE_LENGTH(dataBytesRemaining);
692 
693         if (blockSizeAlignedDataRemaining > 0U)
694         {
695             AESCMACLPF3_processBlocks(plainText, blockSizeAlignedDataRemaining);
696 
697             dataBytesRemaining -= blockSizeAlignedDataRemaining;
698         }
699 
700         if (dataBytesRemaining > 0U)
701         {
702             AESCCMLPF3_processCBCMACFinalBlock(&plainText[operation->inputLength - dataBytesRemaining],
703                                                dataBytesRemaining);
704         }
705     }
706 
707     /* Wait for operation to complete and save the intermediate tag */
708     AESCMACLPF3_readTag(&tag[0]);
709 }
710 
711 /*
712  *  ======== AESCCMLPF3_processOneStepCTRPolling ========
713  */
AESCCMLPF3_processOneStepCTRPolling(AESCCM_OneStepOperation * operation,uint32_t tag[AES_TAG_LENGTH_BYTES/4U])714 static void AESCCMLPF3_processOneStepCTRPolling(AESCCM_OneStepOperation *operation,
715                                                 uint32_t tag[AES_TAG_LENGTH_BYTES / 4U])
716 {
717     /* Init Counter Mode */
718     if (operation->inputLength == 0U)
719     {
720         AESSetAUTOCFG(AESCTRLPF3_LAST_BLOCK_AUTOCFG);
721     }
722     else
723     {
724         AESSetAUTOCFG(AESCTRLPF3_DEFAULT_AUTOCFG);
725     }
726 
727     /* Process counter block with counter value of 0 */
728     AESCCMLPF3_processCTRCounterBlock(operation->nonce, operation->nonceLength, (uint8_t)0U);
729 
730     /* =====================
731      * Process Tag
732      * =====================
733      */
734 
735     /* XOR tag with encrypted counter block to form ciphertext */
736     AESWriteTXTXOR32(tag);
737 
738     /* Read the tag ciphertext and trigger the encryption of the next counter block */
739     AESReadTag32(tag);
740 
741     if (operation->inputLength > 0U)
742     {
743         /* ==================
744          * Process input data
745          * ==================
746          */
747         AESCTRLPF3_processData(operation->input, operation->output, operation->inputLength, true);
748     }
749 }
750 
751 /*
752  *  ======== AESCCMLPF3_processOneStepEncryptPolling ========
753  */
AESCCMLPF3_processOneStepEncryptPolling(AESCCMLPF3_Object * object,AESCCM_OneStepOperation * operation)754 static inline int_fast16_t AESCCMLPF3_processOneStepEncryptPolling(AESCCMLPF3_Object *object,
755                                                                    AESCCM_OneStepOperation *operation)
756 {
757     /* Calculate the MAC for the AAD and message */
758     AESCCMLPF3_processOneStepCBCMACPolling(operation, (uint32_t *)&object->intermediateTag[0], AESCCM_MODE_ENCRYPT);
759 
760     /* Encrypt the MAC and the message */
761     AESCCMLPF3_processOneStepCTRPolling(operation, (uint32_t *)&object->intermediateTag[0]);
762 
763     (void)memcpy((void *)&operation->mac[0], (void *)&object->intermediateTag[0], operation->macLength);
764 
765     /* This operation is always successful */
766     return AESCCM_STATUS_SUCCESS;
767 }
768 
769 /*
770  *  ======== AESCCMLPF3_processOneStepDecryptPolling ========
771  */
AESCCMLPF3_processOneStepDecryptPolling(AESCCMLPF3_Object * object,AESCCM_OneStepOperation * operation)772 static inline int_fast16_t AESCCMLPF3_processOneStepDecryptPolling(AESCCMLPF3_Object *object,
773                                                                    AESCCM_OneStepOperation *operation)
774 {
775     bool macValid;
776     int_fast16_t status = AESCCM_STATUS_MAC_INVALID;
777     uint32_t *mac;
778 
779     /* Use the object's intermediateCounter field which is only used for
780      * segmented operations to store the MAC to save stack space.
781      */
782     mac = (uint32_t *)&object->intermediateCounter[0];
783 
784     /* Create a word-aligned copy of the MAC */
785     (void)memcpy((void *)mac, (void *)operation->mac, operation->macLength);
786 
787     /* Decrypt the MAC and the message */
788     AESCCMLPF3_processOneStepCTRPolling(operation, mac);
789 
790     /* Calculate the MAC on the decrypted message and AAD */
791     AESCCMLPF3_processOneStepCBCMACPolling(operation, (uint32_t *)&object->intermediateTag[0], AESCCM_MODE_DECRYPT);
792 
793     /* Perform a constant time comparision of the calculated MAC and the decrypted MAC */
794     macValid = CryptoUtils_buffersMatch(object->intermediateTag, mac, (size_t)operation->macLength);
795 
796     if (macValid)
797     {
798         status = AESCCM_STATUS_SUCCESS;
799     }
800 
801     return status;
802 }
803 
804 /*
805  *  ======== AESCCMLPF3_oneStepOperation ========
806  */
AESCCMLPF3_oneStepOperation(AESCCM_Handle handle,AESCCM_OneStepOperation * operation,AESCCM_OperationType operationType)807 static int_fast16_t AESCCMLPF3_oneStepOperation(AESCCM_Handle handle,
808                                                 AESCCM_OneStepOperation *operation,
809                                                 AESCCM_OperationType operationType)
810 {
811     DebugP_assert(handle);
812     DebugP_assert(operation);
813     DebugP_assert(operation->key);
814     /* Internally generated nonces aren't supported for now */
815     DebugP_assert(!operation->nonceInternallyGenerated);
816     DebugP_assert(operation->nonce && (operation->nonceLength >= 7U) && (operation->nonceLength <= 13U));
817     DebugP_assert((operation->aad && (operation->aadLength > 0U)) ||
818                   (operation->input && (operation->inputLength > 0U)));
819     DebugP_assert(operation->mac && (operation->macLength <= 16U));
820     /* Implementation only supports aadLength to 65,279 bytes */
821     DebugP_assert(operation->aadLength <= B1_AAD_LENGTH_SMALL_LIMIT)
822 
823         bool dmaActive        = false;
824     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
825     int_fast16_t status;
826 
827 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 0)
828     /* Check word-alignment of input & output pointers */
829     if (!IS_WORD_ALIGNED(operation->input) || !IS_WORD_ALIGNED(operation->output))
830     {
831         return AESCCM_STATUS_UNALIGNED_IO_NOT_SUPPORTED;
832     }
833 #endif
834 
835     /* The nonce length must be 7 to 13 bytes long */
836     if ((operation->nonceLength < (uint8_t)7U) || (operation->nonceLength > (uint8_t)13U))
837     {
838         return AESCCM_STATUS_ERROR;
839     }
840 
841     /* The combined length of AAD and payload data must be non-zero. */
842     if ((operation->aadLength + operation->inputLength) == 0U)
843     {
844         return AESCCM_STATUS_ERROR;
845     }
846 
847     /* Check DMA xfer limit for blocking and callback modes */
848     if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) &&
849         !AESCommonLPF3_isDMALengthValid(operation->input, operation->output, operation->inputLength))
850     {
851         return AESCCM_STATUS_ERROR;
852     }
853 
854     /* Check if there is no operation already in progress for this driver
855      * instance, and then mark the current operation to be in progress.
856      */
857     status = AESCommonLPF3_setOperationInProgress(&object->common);
858 
859     if (status != AES_STATUS_SUCCESS)
860     {
861         return status;
862     }
863 
864     if (!CryptoResourceLPF3_acquireLock(object->common.semaphoreTimeout))
865     {
866         AESCommonLPF3_clearOperationInProgress(&object->common);
867         return AESCCM_STATUS_RESOURCE_UNAVAILABLE;
868     }
869 
870     object->common.cryptoResourceLocked = true;
871     object->common.returnStatus         = AESCCM_STATUS_SUCCESS;
872 
873     AESCommonLPF3_loadKey(operation->key);
874 
875     /* Process all one-step operations with data length less than the DMA size
876      * threshold as a polling mode operation.
877      */
878     if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_POLLING) ||
879         (operation->inputLength < AESCCMLPF3_DMA_SIZE_THRESHOLD))
880     {
881         if (operationType == AESCCM_OP_TYPE_ONESTEP_ENCRYPT)
882         {
883             status = AESCCMLPF3_processOneStepEncryptPolling(object, operation);
884         }
885         else /* operationType == AESCCM_OP_TYPE_ONESTEP_DECRYPT */
886         {
887             status = AESCCMLPF3_processOneStepDecryptPolling(object, operation);
888         }
889     }
890     else
891     {
892         object->operation     = (AESCCM_OperationUnion *)operation;
893         object->operationType = operationType;
894 
895         /* Copy data pointers */
896         object->input  = operation->input;
897         object->output = operation->output;
898         object->mac    = operation->mac;
899         object->aad    = operation->aad;
900         object->nonce  = operation->nonce;
901 
902         /* Copy length info */
903         object->nonceLength                = operation->nonceLength;
904         object->totalAADLength             = operation->aadLength;
905         object->totalDataLength            = operation->inputLength;
906         object->totalCBCMACLengthRemaining = operation->inputLength;
907         object->totalCTRLengthRemaining    = operation->inputLength;
908         object->macLength                  = operation->macLength;
909 
910         /* Init AAD processing vars */
911         object->aadBytesProcessed = 0U;
912         object->bufferedAADLength = (uint8_t)0U;
913 
914         AESCCM_Mode direction = AESCCM_MODE_ENCRYPT;
915 
916         if (operationType == AESCCM_OP_TYPE_ONESTEP_DECRYPT)
917         {
918             direction = AESCCM_MODE_DECRYPT;
919         }
920 
921         if ((operation->aadLength > 0U) && (status == AESCCM_STATUS_SUCCESS))
922         {
923             /* Process the entire AAD using CPU R/W. It is expected that
924              * the AAD length is relatively short (<= 64-bytes). Therefore,
925              * using DMA is inefficient after DMA setup, task switching,
926              * and interrupt overhead are accounted for.
927              */
928             status = AESCCMLPF3_processSegmentedCBCMAC(object, operation->aadLength, 0, direction);
929         }
930 
931         if ((operation->inputLength > 0U) && (status == AESCCM_STATUS_SUCCESS))
932         {
933             /* Process Data with DMA */
934             status    = AESCCMLPF3_addDataDMA(handle, direction, operation->inputLength);
935             dmaActive = true;
936         }
937     }
938 
939     if (!dmaActive)
940     {
941         AESCommonLPF3_clearOperationInProgress(&object->common);
942 
943         /* Cleanup and release crypto resource lock */
944         AESCommonLPF3_cleanup(&object->common);
945 
946         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
947         {
948             object->callbackFxn(handle, status, (AESCCM_OperationUnion *)operation, operationType);
949 
950             /* Always return success in callback mode */
951             status = AESCCM_STATUS_SUCCESS;
952         }
953     }
954 
955     return status;
956 }
957 
958 /*
959  *  ======== AESCCM_oneStepEncrypt ========
960  */
AESCCM_oneStepEncrypt(AESCCM_Handle handle,AESCCM_OneStepOperation * operation)961 int_fast16_t AESCCM_oneStepEncrypt(AESCCM_Handle handle, AESCCM_OneStepOperation *operation)
962 {
963     int_fast16_t status = AESCCM_STATUS_SUCCESS;
964 
965     if (operation->key->encoding == CryptoKey_PLAINTEXT || operation->key->encoding == CryptoKey_KEYSTORE)
966     {
967         status = AESCCMLPF3_oneStepOperation(handle, operation, AESCCM_OP_TYPE_ONESTEP_ENCRYPT);
968     }
969 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
970     else if (operation->key->encoding == CryptoKey_PLAINTEXT_HSM)
971     {
972         status = AESCCMLPF3HSM_oneStepOperation(handle, operation, AESCCM_OP_TYPE_ONESTEP_ENCRYPT);
973     }
974 #endif
975     else
976     {
977         status = AESCCM_STATUS_ERROR;
978     }
979     return status;
980 }
981 
982 /*
983  *  ======== AESCCM_oneStepDecrypt ========
984  */
AESCCM_oneStepDecrypt(AESCCM_Handle handle,AESCCM_OneStepOperation * operation)985 int_fast16_t AESCCM_oneStepDecrypt(AESCCM_Handle handle, AESCCM_OneStepOperation *operation)
986 {
987     int_fast16_t status = AESCCM_STATUS_SUCCESS;
988 
989     if (operation->key->encoding == CryptoKey_PLAINTEXT || operation->key->encoding == CryptoKey_KEYSTORE)
990     {
991         status = AESCCMLPF3_oneStepOperation(handle, operation, AESCCM_OP_TYPE_ONESTEP_DECRYPT);
992     }
993 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
994     else if (operation->key->encoding == CryptoKey_PLAINTEXT_HSM)
995     {
996         status = AESCCMLPF3HSM_oneStepOperation(handle, operation, AESCCM_OP_TYPE_ONESTEP_DECRYPT);
997     }
998 #endif
999     else
1000     {
1001         status = AESCCM_STATUS_ERROR;
1002     }
1003     return status;
1004 }
1005 
1006 /*
1007  *  ======== AESCCMLPF3_setupSegmentedOperation ========
1008  */
AESCCMLPF3_setupSegmentedOperation(AESCCMLPF3_Object * object,const CryptoKey * key,size_t totalAADLength,size_t totalDataLength,size_t macLength)1009 static int_fast16_t AESCCMLPF3_setupSegmentedOperation(AESCCMLPF3_Object *object,
1010                                                        const CryptoKey *key,
1011                                                        size_t totalAADLength,
1012                                                        size_t totalDataLength,
1013                                                        size_t macLength)
1014 {
1015     DebugP_assert(key);
1016 
1017     int_fast16_t status = AESCommonLPF3_setupSegmentedOperation(&object->common, key);
1018 
1019     if (status == AES_STATUS_SUCCESS)
1020     {
1021         /* If the user doesn't provide the total lengths in the setupXXXX()
1022          * calls, they must provide the lengths in setLengths().
1023          */
1024         object->totalAADLength  = totalAADLength;
1025         object->totalDataLength = totalDataLength;
1026         object->macLength       = (uint8_t)macLength;
1027 
1028         object->totalCTRLengthRemaining    = totalDataLength;
1029         object->totalCBCMACLengthRemaining = totalDataLength;
1030         object->aadBytesProcessed          = 0U;
1031         object->bufferedAADLength          = (uint8_t)0U;
1032 
1033         /* Initialize MAC pointer to NULL to avoid premature processing of the
1034          * MAC in the ISR.
1035          */
1036         object->mac = NULL;
1037 
1038         /* Initialize operation pointer to NULL in case AESCCM_cancelOperation
1039          * is called after AESCCM_setupXXXX and callback should be skipped.
1040          */
1041         object->operation = NULL;
1042     }
1043 
1044     return status;
1045 }
1046 
1047 /*
1048  *  ======== AESCCM_setupEncrypt ========
1049  */
AESCCM_setupEncrypt(AESCCM_Handle handle,const CryptoKey * key,size_t totalAADLength,size_t totalPlaintextLength,size_t macLength)1050 int_fast16_t AESCCM_setupEncrypt(AESCCM_Handle handle,
1051                                  const CryptoKey *key,
1052                                  size_t totalAADLength,
1053                                  size_t totalPlaintextLength,
1054                                  size_t macLength)
1055 {
1056     DebugP_assert(handle);
1057     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1058 
1059 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1060     if (key->encoding == CryptoKey_PLAINTEXT_HSM)
1061     {
1062         return AESCCMLPF3HSM_setupEncrypt(handle, key, totalAADLength, totalPlaintextLength, macLength);
1063     }
1064 #endif
1065 
1066     int_fast16_t status = AESCCMLPF3_setupSegmentedOperation(object,
1067                                                              key,
1068                                                              totalAADLength,
1069                                                              totalPlaintextLength,
1070                                                              macLength);
1071     if (status == AES_STATUS_SUCCESS)
1072     {
1073         object->operationType = AESCCM_OPERATION_TYPE_ENCRYPT;
1074     }
1075 
1076     return status;
1077 }
1078 
1079 /*
1080  *  ======== AESCCM_setupDecrypt ========
1081  */
AESCCM_setupDecrypt(AESCCM_Handle handle,const CryptoKey * key,size_t totalAADLength,size_t totalPlaintextLength,size_t macLength)1082 int_fast16_t AESCCM_setupDecrypt(AESCCM_Handle handle,
1083                                  const CryptoKey *key,
1084                                  size_t totalAADLength,
1085                                  size_t totalPlaintextLength,
1086                                  size_t macLength)
1087 {
1088     DebugP_assert(handle);
1089 
1090     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1091 
1092 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1093     if (key->encoding == CryptoKey_PLAINTEXT_HSM)
1094     {
1095         return AESCCMLPF3HSM_setupDecrypt(handle, key, totalAADLength, totalPlaintextLength, macLength);
1096     }
1097 #endif
1098 
1099     int_fast16_t status = AESCCMLPF3_setupSegmentedOperation(object,
1100                                                              key,
1101                                                              totalAADLength,
1102                                                              totalPlaintextLength,
1103                                                              macLength);
1104     if (status == AESCCM_STATUS_SUCCESS)
1105     {
1106         object->operationType = AESCCM_OPERATION_TYPE_DECRYPT;
1107     }
1108 
1109     return status;
1110 }
1111 
1112 /*
1113  *  ======== AESCCM_setLengths ========
1114  */
AESCCM_setLengths(AESCCM_Handle handle,size_t aadLength,size_t plaintextLength,size_t macLength)1115 int_fast16_t AESCCM_setLengths(AESCCM_Handle handle, size_t aadLength, size_t plaintextLength, size_t macLength)
1116 {
1117     DebugP_assert(handle);
1118 
1119     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1120 
1121     /* This shouldn't be called after addXXX() or finalizeXXX() */
1122     DebugP_assert(object->operationType == AESCCM_OPERATION_TYPE_DECRYPT ||
1123                   object->operationType == AESCCM_OPERATION_TYPE_ENCRYPT);
1124 
1125     /* Don't continue the segmented operation if there
1126      * was an error or a cancellation
1127      */
1128     if (object->common.returnStatus != AESCCM_STATUS_SUCCESS)
1129     {
1130         return object->common.returnStatus;
1131     }
1132 
1133     /* The combined length of AAD and payload data must be non-zero. */
1134     if ((aadLength == 0U) && (plaintextLength == 0U))
1135     {
1136         return AESCCM_STATUS_ERROR;
1137     }
1138 
1139     object->totalAADLength             = aadLength;
1140     object->totalDataLength            = plaintextLength;
1141     object->totalCBCMACLengthRemaining = plaintextLength;
1142     object->totalCTRLengthRemaining    = plaintextLength;
1143     object->macLength                  = (uint8_t)macLength;
1144 
1145     return AESCCM_STATUS_SUCCESS;
1146 }
1147 
1148 /*
1149  *  ======== AESCCM_setNonce ========
1150  */
AESCCM_setNonce(AESCCM_Handle handle,const uint8_t * nonce,size_t nonceLength)1151 int_fast16_t AESCCM_setNonce(AESCCM_Handle handle, const uint8_t *nonce, size_t nonceLength)
1152 {
1153     DebugP_assert(handle);
1154     DebugP_assert(nonce);
1155 
1156     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1157 
1158     /* This function cannot be called after addXXX() or finalizeXXX() */
1159     DebugP_assert((object->operationType == AESCCM_OPERATION_TYPE_DECRYPT) ||
1160                   (object->operationType == AESCCM_OPERATION_TYPE_ENCRYPT));
1161 
1162     /* Don't continue the segmented operation if there
1163      * was an error during setup.
1164      */
1165     if (object->common.returnStatus != AESCCM_STATUS_SUCCESS)
1166     {
1167         return object->common.returnStatus;
1168     }
1169 
1170     /* The nonce length must be 7 to 13 bytes long */
1171     if ((nonceLength < 7U) || (nonceLength > 13U))
1172     {
1173         return AESCCM_STATUS_ERROR;
1174     }
1175 
1176     object->nonce       = nonce;
1177     object->nonceLength = (uint8_t)nonceLength;
1178 
1179     return AESCCM_STATUS_SUCCESS;
1180 }
1181 
1182 /*
1183  *  ======== AESCCM_generateNonce ========
1184  */
AESCCM_generateNonce(AESCCM_Handle handle,uint8_t * nonce,size_t nonceSize,size_t * nonceLength)1185 int_fast16_t AESCCM_generateNonce(AESCCM_Handle handle, uint8_t *nonce, size_t nonceSize, size_t *nonceLength)
1186 {
1187     DebugP_assert(handle);
1188     DebugP_assert(nonce);
1189     DebugP_assert(nonceSize > 0U);
1190     DebugP_assert(nonceLength);
1191 
1192     /* This feature is not currently supported */
1193     return AESCCM_STATUS_FEATURE_NOT_SUPPORTED;
1194 }
1195 
1196 /*
1197  *  ======== AESCCMLPF3_processSegmentedCBCMAC ========
1198  */
AESCCMLPF3_processSegmentedCBCMAC(AESCCMLPF3_Object * object,size_t aadSegmentLength,size_t dataSegmentLength,AESCCM_Mode direction)1199 static int_fast16_t AESCCMLPF3_processSegmentedCBCMAC(AESCCMLPF3_Object *object,
1200                                                       size_t aadSegmentLength,
1201                                                       size_t dataSegmentLength,
1202                                                       AESCCM_Mode direction)
1203 {
1204     bool dmaActive            = false;
1205     int_fast16_t status       = AESCCM_STATUS_SUCCESS;
1206     size_t aadBytesRemaining  = 0U;
1207     size_t dataBytesRemaining = 0U;
1208 
1209     AESSetAUTOCFG(AESCMACLPF3_DEFAULT_AUTOCFG);
1210 
1211     /* Process B0 block if no AAD and no data has been proceeded yet */
1212     if ((object->aadBytesProcessed == 0U) && (object->totalCBCMACLengthRemaining == object->totalDataLength))
1213     {
1214         /* Set IV to zero */
1215         AESClearIV();
1216 
1217         AESCCMLPF3_processB0(object->nonce,
1218                              object->nonceLength,
1219                              object->totalAADLength,
1220                              object->totalDataLength,
1221                              object->macLength);
1222     }
1223     else
1224     {
1225         /* Restore intermediate tag */
1226         AESWriteTag32((uint32_t *)&object->intermediateTag[0]);
1227     }
1228 
1229     /* ===========
1230      * Process AAD
1231      * ===========
1232      */
1233     if (aadSegmentLength > 0U)
1234     {
1235         aadBytesRemaining = aadSegmentLength;
1236 
1237         if (object->aadBytesProcessed == 0U)
1238         {
1239             /* Process B1 with AAD */
1240             object->aadBytesProcessed = AESCCMLPF3_processB1withAAD(object->aad,
1241                                                                     aadSegmentLength,
1242                                                                     object->totalAADLength);
1243             aadBytesRemaining -= object->aadBytesProcessed;
1244         }
1245 
1246         /* Process any remaining AAD */
1247         if (aadBytesRemaining > 0U)
1248         {
1249             /* Check for any buffered AAD from the previous transaction.
1250              * Due to the AAD length parameter restrictions on AESCCM_addAAD(),
1251              * there always must be two bytes of buffered AAD if non-zero.
1252              */
1253             if (object->bufferedAADLength > (uint8_t)0U)
1254             {
1255                 AES_BlockWordAligned aadBlock;
1256 
1257                 aadBlock.words[0] = (uint32_t)0U;
1258                 aadBlock.words[1] = (uint32_t)0U;
1259                 aadBlock.words[2] = (uint32_t)0U;
1260                 aadBlock.words[3] = (uint32_t)0U;
1261 
1262                 /* Copy buffered AAD into the local AAD block */
1263                 aadBlock.bytes[0] = object->bufferedAAD[0];
1264                 aadBlock.bytes[1] = object->bufferedAAD[1];
1265 
1266                 size_t aadBlockBytesAvail = (AES_BLOCK_SIZE - AESCCMLPF3_AAD_BUFFER_SIZE);
1267                 const uint8_t *newAAD     = &object->aad[aadSegmentLength - aadBytesRemaining];
1268 
1269                 /* Copy the new AAD into the local AAD block */
1270                 if (aadBytesRemaining >= aadBlockBytesAvail)
1271                 {
1272                     (void)memcpy((void *)&aadBlock.bytes[AESCCMLPF3_AAD_BUFFER_SIZE],
1273                                  (void *)newAAD,
1274                                  aadBlockBytesAvail);
1275 
1276                     object->aadBytesProcessed += AES_BLOCK_SIZE;
1277                     aadBytesRemaining -= aadBlockBytesAvail;
1278                 }
1279                 else
1280                 {
1281                     (void)memcpy((void *)&aadBlock.bytes[AESCCMLPF3_AAD_BUFFER_SIZE],
1282                                  (void *)newAAD,
1283                                  aadBytesRemaining);
1284 
1285                     object->aadBytesProcessed += (aadBytesRemaining + AESCCMLPF3_AAD_BUFFER_SIZE);
1286                     aadBytesRemaining = 0U;
1287                 }
1288 
1289                 AESCMACLPF3_processBlocks(aadBlock.bytes, sizeof(aadBlock));
1290 
1291                 object->bufferedAADLength = (uint8_t)0U;
1292             }
1293 
1294             size_t blockSizeAlignedAADLength = AES_BLOCK_SIZE_MULTIPLE_LENGTH(aadBytesRemaining);
1295 
1296             if (blockSizeAlignedAADLength > 0U)
1297             {
1298                 AESCMACLPF3_processBlocks(&object->aad[aadSegmentLength - aadBytesRemaining],
1299                                           blockSizeAlignedAADLength);
1300 
1301                 object->aadBytesProcessed += blockSizeAlignedAADLength;
1302                 aadBytesRemaining -= blockSizeAlignedAADLength;
1303             }
1304 
1305             if (aadBytesRemaining > 0U)
1306             {
1307                 if ((object->aadBytesProcessed + aadBytesRemaining) == object->totalAADLength)
1308                 {
1309                     AESCCMLPF3_processCBCMACFinalBlock(&object->aad[aadSegmentLength - aadBytesRemaining],
1310                                                        aadBytesRemaining);
1311                     object->aadBytesProcessed += aadBytesRemaining;
1312                 }
1313                 else if (aadBytesRemaining == AESCCMLPF3_AAD_BUFFER_SIZE)
1314                 {
1315                     /* Save leftover AAD bytes to process later */
1316                     const uint8_t *aadRemaining = &object->aad[aadSegmentLength - AESCCMLPF3_AAD_BUFFER_SIZE];
1317                     object->bufferedAAD[0]      = *aadRemaining;
1318                     object->bufferedAAD[1]      = *(aadRemaining + 1U);
1319                     object->bufferedAADLength   = (uint8_t)AESCCMLPF3_AAD_BUFFER_SIZE;
1320                 }
1321                 else
1322                 {
1323                     /* This should never happen if API restrictions on AAD length are followed */
1324                     AESAbort();
1325                     return AESCCM_STATUS_ERROR;
1326                 }
1327             }
1328         }
1329     }
1330 
1331     /* ============
1332      * Process Data
1333      * ============
1334      */
1335     if (dataSegmentLength > 0U)
1336     {
1337         dataBytesRemaining = dataSegmentLength;
1338 
1339         /* Perform CBC-MAC on plaintext data:
1340          *  - For encryption, plaintext data points to object's input.
1341          *  - For decryption, plaintext data points to object's output.
1342          */
1343         const uint8_t *plainText = object->input;
1344         if (direction == AESCCM_MODE_DECRYPT)
1345         {
1346             plainText = object->output;
1347         }
1348 
1349         size_t blockSizeAlignedDataRemaining = AES_BLOCK_SIZE_MULTIPLE_LENGTH(dataBytesRemaining);
1350 
1351         if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_POLLING) ||
1352             (blockSizeAlignedDataRemaining < AESCCMLPF3_DMA_SIZE_THRESHOLD))
1353         {
1354             /* Process all the full blocks of data */
1355             if (blockSizeAlignedDataRemaining > 0U)
1356             {
1357                 AESCMACLPF3_processBlocks(plainText, blockSizeAlignedDataRemaining);
1358 
1359                 dataBytesRemaining -= blockSizeAlignedDataRemaining;
1360             }
1361 
1362             if (dataBytesRemaining > 0U)
1363             {
1364                 AESCCMLPF3_processCBCMACFinalBlock(&plainText[dataSegmentLength - dataBytesRemaining],
1365                                                    dataBytesRemaining);
1366             }
1367 
1368             object->inputCBCMACLengthRemaining -= dataSegmentLength;
1369             object->totalCBCMACLengthRemaining -= dataSegmentLength;
1370         }
1371         else
1372         {
1373             /* Clear BUSHALT when using DMA */
1374             AESClearAUTOCFGBusHalt();
1375 
1376             /* Setup DMA configuration and set power constraint */
1377             AESCommonLPF3_setupDMA(&object->common, AESCBCMACLPF3_DMA_CONFIG);
1378 
1379             AESCommonLPF3_configInputDMA(plainText, blockSizeAlignedDataRemaining);
1380 
1381             /* Enable interrupt upon input DMA done */
1382             AESSetIMASK((uint32_t)AES_IMASK_CHADONE_M);
1383 
1384             object->inputCBCMACLengthRemaining -= blockSizeAlignedDataRemaining;
1385             object->totalCBCMACLengthRemaining -= blockSizeAlignedDataRemaining;
1386 
1387             dmaActive = true;
1388 
1389             /* Manually trigger the DMA to start the CBC-MAC operation */
1390             AESSetTrigger((uint32_t)AES_TRG_DMACHA);
1391         }
1392     }
1393 
1394     if (dmaActive)
1395     {
1396         status = AESCCMLPF3_waitForDMA(object);
1397     }
1398     else
1399     {
1400         /* Wait for operation to complete and save the intermediate tag */
1401         AESCMACLPF3_readTag((uint32_t *)&object->intermediateTag[0]);
1402     }
1403 
1404     return status;
1405 }
1406 
1407 /*
1408  *  ======== AESCCMLPF3_processCTRCounterBlock ========
1409  */
AESCCMLPF3_processCTRCounterBlock(const uint8_t * nonce,uint8_t nonceLength,uint8_t counterVal)1410 static void AESCCMLPF3_processCTRCounterBlock(const uint8_t *nonce, uint8_t nonceLength, uint8_t counterVal)
1411 {
1412     /* ============================================
1413      * Initial flags, nonce, and counter formatting per RFC3610:
1414      *    Octet Number   Contents
1415      *    ------------   ---------
1416      *    0              Flags
1417      *    1 ... 15-L     Nonce N
1418      *    16-L ... 15    Counter i (most-significant-byte first)
1419      *
1420      * The Flags field is formatted as follows:
1421      *
1422      *    Bit Number   Contents
1423      *    ----------   ----------------------
1424      *    7            Reserved (always zero)
1425      *    6            Reserved (always zero)
1426      *    5 ... 3      Zero
1427      *    2 ... 0      L'
1428      *
1429      *   where L' = 14 - nonceLength
1430      * ============================================
1431      */
1432     AES_BlockWordAligned counter;
1433 
1434     counter.words[0] = (uint32_t)0U;
1435     counter.words[1] = (uint32_t)0U;
1436     counter.words[2] = (uint32_t)0U;
1437     counter.words[3] = (uint32_t)0U;
1438 
1439     counter.bytes[0] = (uint8_t)14U - nonceLength;
1440 
1441     (void)memcpy((void *)&counter.bytes[1], (void *)nonce, nonceLength);
1442 
1443     counter.bytes[15] = counterVal;
1444 
1445     /* Initial write to AES_O_BUF3 triggers the encryption */
1446     AESCTRLPF3_writeCounter(counter.words);
1447 
1448     /* Wait for encryption of counter block to complete */
1449     while (AESGetStatus() != (uint32_t)AES_STA_STATE_IDLE) {}
1450 }
1451 
1452 /*
1453  *  ======== AESCCMLPF3_processTagCTR ========
1454  */
AESCCMLPF3_processTagCTR(AESCCMLPF3_Object * object)1455 static void AESCCMLPF3_processTagCTR(AESCCMLPF3_Object *object)
1456 {
1457     /* Use default CTR config without AES_AUTOCFG_TRGAES_RDTXT3
1458      * to avoid triggering an encryption of the next counter value
1459      * when reading out the encrypted tag.
1460      */
1461     AESSetAUTOCFG(AESCTRLPF3_LAST_BLOCK_AUTOCFG);
1462 
1463     /* Process counter block with counter value of 0 */
1464     AESCCMLPF3_processCTRCounterBlock(object->nonce, object->nonceLength, (uint8_t)0U);
1465 
1466     /* XOR tag with encrypted counter block to form ciphertext */
1467     AESWriteTXTXOR32((uint32_t *)&object->intermediateTag[0]);
1468 
1469     /* Read the tag ciphertext */
1470     AESReadTag32((uint32_t *)&object->intermediateTag[0]);
1471 }
1472 
1473 /*
1474  *  ======== AESCCMLPF3_processSegmentedCTR ========
1475  */
AESCCMLPF3_processSegmentedCTR(AESCCMLPF3_Object * object,size_t dataSegmentLength)1476 static int_fast16_t AESCCMLPF3_processSegmentedCTR(AESCCMLPF3_Object *object, size_t dataSegmentLength)
1477 {
1478     bool dmaActive      = false;
1479     bool firstCounter   = false;
1480     int_fast16_t status = AESCCM_STATUS_SUCCESS;
1481 
1482     if (object->totalCTRLengthRemaining == object->totalDataLength)
1483     {
1484         firstCounter = true;
1485     }
1486 
1487     AESSetAUTOCFG(AESCTRLPF3_DEFAULT_AUTOCFG);
1488 
1489     if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) &&
1490         (dataSegmentLength >= AESCCMLPF3_DMA_SIZE_THRESHOLD))
1491     {
1492         size_t bytesProcessed;
1493 
1494         bytesProcessed = AESCTRLPF3_configDataDMA(&object->common, object->input, object->output, dataSegmentLength);
1495 
1496         object->totalCTRLengthRemaining -= bytesProcessed;
1497         object->inputCTRLengthRemaining -= bytesProcessed;
1498 
1499         dmaActive = true;
1500     }
1501 
1502     /* Writing the counter value will trigger the first encryption */
1503     if (firstCounter)
1504     {
1505         /* Process counter block with initial counter value of 1 */
1506         AESCCMLPF3_processCTRCounterBlock(object->nonce, object->nonceLength, (uint8_t)1U);
1507     }
1508     else
1509     {
1510         /* Restore intermediate counter */
1511         AESCTRLPF3_writeCounter((uint32_t *)&object->intermediateCounter[0]);
1512     }
1513 
1514     if (dmaActive)
1515     {
1516         status = AESCCMLPF3_waitForDMA(object);
1517     }
1518     else
1519     {
1520         /* Process data with CPU R/W */
1521         AESCTRLPF3_processData(object->input, object->output, dataSegmentLength, false);
1522 
1523         object->totalCTRLengthRemaining -= dataSegmentLength;
1524 
1525         /* Store the counter */
1526         AESCTRLPF3_readCounter((uint32_t *)&object->intermediateCounter[0]);
1527     }
1528 
1529     return status;
1530 }
1531 
1532 /*
1533  *  ======== AESCCM_addAAD ========
1534  */
AESCCM_addAAD(AESCCM_Handle handle,AESCCM_SegmentedAADOperation * operation)1535 int_fast16_t AESCCM_addAAD(AESCCM_Handle handle, AESCCM_SegmentedAADOperation *operation)
1536 {
1537     DebugP_assert(handle);
1538     DebugP_assert(operation);
1539 
1540     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1541 
1542 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1543     if (object->common.key.encoding == CryptoKey_PLAINTEXT_HSM)
1544     {
1545         return AESCCMLPF3HSM_addAAD(handle, operation);
1546     }
1547 #endif
1548 
1549     int_fast16_t status;
1550 
1551     object->operation = (AESCCM_OperationUnion *)operation;
1552 
1553     /* Don't continue the segmented operation if there
1554      * was an error or a cancellation.
1555      */
1556     if (object->common.returnStatus != AESCCM_STATUS_SUCCESS)
1557     {
1558         return object->common.returnStatus;
1559     }
1560 
1561     /* This operation can be called after setup or after addAAD again. */
1562     DebugP_assert((object->operationType == AESCCM_OPERATION_TYPE_DECRYPT) ||
1563                   (object->operationType == AESCCM_OPERATION_TYPE_ENCRYPT) ||
1564                   (object->operationType == AESCCM_OP_TYPE_AAD_DECRYPT) ||
1565                   (object->operationType == AESCCM_OP_TYPE_AAD_ENCRYPT));
1566 
1567     size_t calcAADLen = object->aadBytesProcessed + (size_t)object->bufferedAADLength + operation->aadLength;
1568 
1569     /* The input length must be a non-zero multiple of an AES block size
1570      * unless you are dealing with the last chunk of AAD.
1571      */
1572     if ((operation->aadLength == 0U) ||
1573         ((AES_NON_BLOCK_SIZE_MULTIPLE_LENGTH(operation->aadLength) > 0U) && (calcAADLen != object->totalAADLength)))
1574     {
1575         return AESCCM_STATUS_ERROR;
1576     }
1577 
1578     /* The total AAD input length must not exceed the total length specified
1579      * in AESCCM_setLengths() or the setupXXXX() call.
1580      */
1581     if (calcAADLen > object->totalAADLength)
1582     {
1583         return AESCCM_STATUS_ERROR;
1584     }
1585 
1586     AESCCM_Mode direction              = AESCCM_MODE_ENCRYPT;
1587     AESCCM_OperationType operationType = AESCCM_OP_TYPE_AAD_ENCRYPT;
1588 
1589     if ((object->operationType == AESCCM_OPERATION_TYPE_DECRYPT) ||
1590         (object->operationType == AESCCM_OP_TYPE_AAD_DECRYPT))
1591     {
1592         direction     = AESCCM_MODE_DECRYPT;
1593         operationType = AESCCM_OP_TYPE_AAD_DECRYPT;
1594     }
1595 
1596     if (!CryptoResourceLPF3_acquireLock(object->common.semaphoreTimeout))
1597     {
1598         return AESCCM_STATUS_RESOURCE_UNAVAILABLE;
1599     }
1600 
1601     object->common.cryptoResourceLocked = true;
1602 
1603     /* Load only the key into the AES engine now. The AUTOCFG values are loaded as needed
1604      * depending on whether it's a CTR operation or a CBC-MAC operation.
1605      */
1606     AESCommonLPF3_loadKey(&object->common.key);
1607 
1608     object->operationType = operationType;
1609     object->aad           = operation->aad;
1610 
1611     /* AAD is expected to be relatively short in length (< a few AES blocks)
1612      * so DMA is not utilized for blocking and callback modes because the
1613      * interrupt and task switching overhead would outweigh any CPU cycles
1614      * saved using DMA. Code size and complexity is reduced by not supporting
1615      * DMA for AAD.
1616      */
1617 
1618     status = AESCCMLPF3_processSegmentedCBCMAC(object, operation->aadLength, 0, direction);
1619 
1620     if ((status == AESCCM_STATUS_SUCCESS) && (object->totalDataLength == 0U) &&
1621         (object->aadBytesProcessed == object->totalAADLength))
1622     {
1623         AESCCMLPF3_processTagCTR(object);
1624     }
1625 
1626     /* Cleanup and release crypto resource lock */
1627     AESCommonLPF3_cleanup(&object->common);
1628 
1629     object->common.returnStatus = status;
1630 
1631     if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
1632     {
1633         object->callbackFxn(handle, status, (AESCCM_OperationUnion *)operation, operationType);
1634 
1635         /* Always return success in callback mode */
1636         status = AESCCM_STATUS_SUCCESS;
1637     }
1638 
1639     return status;
1640 }
1641 
1642 /*
1643  *  ======== AESCCMLPF3_addDataDMA ========
1644  */
AESCCMLPF3_addDataDMA(AESCCM_Handle handle,AESCCM_Mode direction,size_t inputLength)1645 static int_fast16_t AESCCMLPF3_addDataDMA(AESCCM_Handle handle, AESCCM_Mode direction, size_t inputLength)
1646 {
1647     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1648     int_fast16_t status;
1649 
1650     object->inputLength                = inputLength;
1651     object->inputCBCMACLengthRemaining = inputLength;
1652 
1653     object->inputLength             = inputLength;
1654     object->inputCTRLengthRemaining = inputLength;
1655 
1656     /* We need to set the HWI function and priority since the same physical
1657      * interrupt is shared by multiple drivers and they all need to coexist.
1658      * Whenever a driver starts an operation, it registers its HWI callback
1659      * with the OS.
1660      */
1661     AESCCMLPF3_HWAttrs const *hwAttrs = handle->hwAttrs;
1662     AESCommonLPF3_setupHwi(AESCCMLPF3_hwiFxn, (uintptr_t)handle, hwAttrs->intPriority);
1663 
1664     if (direction == AESCCM_MODE_ENCRYPT)
1665     {
1666         status = AESCCMLPF3_processSegmentedCBCMAC(object, 0U, inputLength, AESCCM_MODE_ENCRYPT);
1667     }
1668     else
1669     {
1670         status = AESCCMLPF3_processSegmentedCTR(object, inputLength);
1671     }
1672 
1673     return status;
1674 }
1675 
1676 /*
1677  *  ======== AESCCMLPF3_addData ========
1678  */
AESCCMLPF3_addData(AESCCM_Handle handle,AESCCM_OperationType operationType,AESCCM_OperationUnion * operation,const uint8_t * input,uint8_t * output,size_t inputLength)1679 static int_fast16_t AESCCMLPF3_addData(AESCCM_Handle handle,
1680                                        AESCCM_OperationType operationType,
1681                                        AESCCM_OperationUnion *operation,
1682                                        const uint8_t *input,
1683                                        uint8_t *output,
1684                                        size_t inputLength)
1685 {
1686     int_fast16_t status       = AESCCM_STATUS_SUCCESS;
1687     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1688 
1689     if (!CryptoResourceLPF3_acquireLock(object->common.semaphoreTimeout))
1690     {
1691         return AESCCM_STATUS_RESOURCE_UNAVAILABLE;
1692     }
1693 
1694     object->common.cryptoResourceLocked = true;
1695 
1696     /* Load only the key into the AES engine now. The AUTOCFG values are loaded as needed
1697      * depending on whether it's a CTR operation or a CBC-MAC operation.
1698      */
1699     AESCommonLPF3_loadKey(&object->common.key);
1700 
1701     object->operationType = operationType;
1702     object->operation     = operation;
1703 
1704     object->input  = input;
1705     object->output = output;
1706 
1707     AESCCM_Mode direction = AESCCM_MODE_ENCRYPT;
1708 
1709     if ((object->operationType == AESCCM_OP_TYPE_DATA_DECRYPT) ||
1710         (object->operationType == AESCCM_OP_TYPE_FINALIZE_DECRYPT))
1711     {
1712         direction = AESCCM_MODE_DECRYPT;
1713     }
1714 
1715     /* Process all segmented operations with data length less than the DMA
1716      * size threshold as a polling mode operation.
1717      */
1718     if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_POLLING) || (inputLength < AESCCMLPF3_DMA_SIZE_THRESHOLD))
1719     {
1720         if (direction == AESCCM_MODE_ENCRYPT)
1721         {
1722             status = AESCCMLPF3_processSegmentedCBCMAC(object, 0, inputLength, AESCCM_MODE_ENCRYPT);
1723         }
1724 
1725         if (status == AESCCM_STATUS_SUCCESS)
1726         {
1727             status = AESCCMLPF3_processSegmentedCTR(object, inputLength);
1728         }
1729 
1730         if ((direction == AESCCM_MODE_DECRYPT) && (status == AESCCM_STATUS_SUCCESS))
1731         {
1732             status = AESCCMLPF3_processSegmentedCBCMAC(object, 0U, inputLength, AESCCM_MODE_DECRYPT);
1733         }
1734 
1735         if ((object->totalCBCMACLengthRemaining == 0U) && (status == AESCCM_STATUS_SUCCESS))
1736         {
1737             AESCCMLPF3_processTagCTR(object);
1738         }
1739 
1740         object->common.returnStatus = status;
1741 
1742         /* Cleanup and release crypto resource lock */
1743         AESCommonLPF3_cleanup(&object->common);
1744     }
1745     else
1746     {
1747         status = AESCCMLPF3_addDataDMA(handle, direction, inputLength);
1748 
1749         if (status != AESCCM_STATUS_SUCCESS)
1750         {
1751             object->common.returnStatus = status;
1752 
1753             /* Cleanup and release crypto resource lock */
1754             AESCommonLPF3_cleanup(&object->common);
1755         }
1756     }
1757 
1758     return status;
1759 }
1760 
1761 /*
1762  *  ======== AESCCM_addData ========
1763  */
AESCCM_addData(AESCCM_Handle handle,AESCCM_SegmentedDataOperation * operation)1764 int_fast16_t AESCCM_addData(AESCCM_Handle handle, AESCCM_SegmentedDataOperation *operation)
1765 {
1766     DebugP_assert(handle);
1767     DebugP_assert(operation);
1768 
1769     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1770     int_fast16_t status       = AESCCM_STATUS_ERROR;
1771 
1772     /* This operation can be called after setupXXXX, addAAD, or addData */
1773     DebugP_assert((object->operationType == AESCCM_OP_TYPE_AAD_ENCRYPT) ||
1774                   (object->operationType == AESCCM_OP_TYPE_DATA_ENCRYPT));
1775 
1776     if (object->common.returnStatus != AESCCM_STATUS_SUCCESS)
1777     {
1778         return object->common.returnStatus;
1779     }
1780 
1781 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 0)
1782     /* Check word-alignment of input & output pointers */
1783     if (!IS_WORD_ALIGNED(operation->input) || !IS_WORD_ALIGNED(operation->output))
1784     {
1785         return AESCCM_STATUS_UNALIGNED_IO_NOT_SUPPORTED;
1786     }
1787 #endif
1788 
1789 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1790     if (object->common.key.encoding == CryptoKey_PLAINTEXT_HSM)
1791     {
1792         /* The input length must be a non-zero multiple of an AES block size
1793          * unless you are dealing with the last chunk of payload data
1794          */
1795         if ((operation->inputLength == 0U) || ((AES_NON_BLOCK_SIZE_MULTIPLE_LENGTH(operation->inputLength) > 0U) &&
1796                                                (operation->inputLength != object->totalDataLengthRemaining)))
1797         {
1798             return AESCCM_STATUS_ERROR;
1799         }
1800 
1801         /* The total input length must not exceed the lengths specified in
1802          * AESCCM_setLengths() or setupXXXX().
1803          */
1804         if (operation->inputLength > object->totalDataLengthRemaining)
1805         {
1806             return AESCCM_STATUS_ERROR;
1807         }
1808     }
1809     else
1810 #endif
1811     {
1812         /* The input length must be a non-zero multiple of an AES block size
1813          * unless you are dealing with the last chunk of payload data
1814          */
1815         if ((operation->inputLength == 0U) || ((AES_NON_BLOCK_SIZE_MULTIPLE_LENGTH(operation->inputLength) > 0U) &&
1816                                                (operation->inputLength != object->totalCBCMACLengthRemaining)))
1817         {
1818             return AESCCM_STATUS_ERROR;
1819         }
1820 
1821         /* The total input length must not exceed the lengths specified in
1822          * AESCCM_setLengths() or setupXXXX().
1823          */
1824         if (operation->inputLength > object->totalCBCMACLengthRemaining)
1825         {
1826             return AESCCM_STATUS_ERROR;
1827         }
1828     }
1829 
1830     /* The AAD input length specified so far must match the total length
1831      * specified in the setLengths() or setupXXXX() calls.
1832      * All AAD input must be processed at this point.
1833      */
1834     if (object->aadBytesProcessed != object->totalAADLength
1835 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1836         && (object->common.key.encoding == CryptoKey_PLAINTEXT || object->common.key.encoding == CryptoKey_KEYSTORE)
1837 #endif
1838     )
1839     {
1840         return AESCCM_STATUS_ERROR;
1841     }
1842 
1843     /* Check DMA xfer limit for blocking and callback modes */
1844     if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) &&
1845         !AESCommonLPF3_isDMALengthValid(operation->input, operation->output, operation->inputLength))
1846     {
1847         return AESCCM_STATUS_ERROR;
1848     }
1849 
1850     AESCCM_OperationType operationType = AESCCM_OP_TYPE_DATA_ENCRYPT;
1851 
1852     if ((object->operationType == AESCCM_OPERATION_TYPE_DECRYPT) ||
1853         (object->operationType == AESCCM_OP_TYPE_AAD_DECRYPT) || (object->operationType == AESCCM_OP_TYPE_DATA_DECRYPT))
1854     {
1855         operationType = AESCCM_OP_TYPE_DATA_DECRYPT;
1856     }
1857 
1858     if (object->common.key.encoding == CryptoKey_PLAINTEXT || object->common.key.encoding == CryptoKey_KEYSTORE)
1859     {
1860         status = AESCCMLPF3_addData(handle,
1861                                     operationType,
1862                                     (AESCCM_OperationUnion *)operation,
1863                                     operation->input,
1864                                     operation->output,
1865                                     operation->inputLength);
1866     }
1867 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1868     else if (object->common.key.encoding == CryptoKey_PLAINTEXT_HSM)
1869     {
1870         status = AESCCMLPF3HSM_addData(handle,
1871                                        operationType,
1872                                        (AESCCM_OperationUnion *)operation,
1873                                        operation->input,
1874                                        operation->output,
1875                                        operation->inputLength);
1876         return status;
1877     }
1878 #endif
1879     else
1880     {
1881         status = AESCCM_STATUS_ERROR;
1882     }
1883 
1884     if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK) &&
1885         (operation->inputLength < AESCCMLPF3_DMA_SIZE_THRESHOLD))
1886     {
1887         object->callbackFxn(handle, status, (AESCCM_OperationUnion *)operation, operationType);
1888 
1889         /* Always return success in callback mode */
1890         status = AESCCM_STATUS_SUCCESS;
1891     }
1892 
1893     return status;
1894 }
1895 
1896 /*
1897  *  ======== AESCCM_finalizeEncrypt ========
1898  */
AESCCM_finalizeEncrypt(AESCCM_Handle handle,AESCCM_SegmentedFinalizeOperation * operation)1899 int_fast16_t AESCCM_finalizeEncrypt(AESCCM_Handle handle, AESCCM_SegmentedFinalizeOperation *operation)
1900 {
1901     DebugP_assert(handle);
1902     DebugP_assert(operation);
1903 
1904     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1905 
1906 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1907     if (object->common.key.encoding == CryptoKey_PLAINTEXT_HSM)
1908     {
1909         return AESCCMLPF3HSM_finalizeEncrypt(handle, operation);
1910     }
1911 #endif
1912 
1913     int_fast16_t status;
1914 
1915     status = AESCCMLPF3_performFinalizeChecks(object, operation);
1916 
1917     if (status != AESCCM_STATUS_SUCCESS)
1918     {
1919         return status;
1920     }
1921 
1922     if (operation->inputLength > 0U)
1923     {
1924         object->mac       = operation->mac;
1925         object->macLength = operation->macLength;
1926 
1927         status = AESCCMLPF3_addData(handle,
1928                                     AESCCM_OP_TYPE_FINALIZE_ENCRYPT,
1929                                     (AESCCM_OperationUnion *)operation,
1930                                     operation->input,
1931                                     operation->output,
1932                                     operation->inputLength);
1933     }
1934 
1935     /* If the return behavior is polling or the operation is finalized with
1936      * input length less than the DMA size threshold (which includes the case
1937      * of finalizing without any additional data), all data processing will
1938      * be complete at this point.
1939      */
1940     if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_POLLING) ||
1941         (operation->inputLength < AESCCMLPF3_DMA_SIZE_THRESHOLD))
1942     {
1943         if (status == AESCCM_STATUS_SUCCESS)
1944         {
1945             (void)memcpy(operation->mac, (uint32_t *)&object->intermediateTag[0], operation->macLength);
1946         }
1947         else
1948         {
1949             object->common.returnStatus = status;
1950         }
1951 
1952         AESCommonLPF3_clearOperationInProgress(&object->common);
1953 
1954         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
1955         {
1956             object->callbackFxn(handle, status, (AESCCM_OperationUnion *)operation, AESCCM_OP_TYPE_FINALIZE_ENCRYPT);
1957 
1958             /* Always return success in callback mode */
1959             status = AESCCM_STATUS_SUCCESS;
1960         }
1961     }
1962 
1963     return status;
1964 }
1965 
1966 /*
1967  *  ======== AESCCM_finalizeDecrypt ========
1968  */
AESCCM_finalizeDecrypt(AESCCM_Handle handle,AESCCM_SegmentedFinalizeOperation * operation)1969 int_fast16_t AESCCM_finalizeDecrypt(AESCCM_Handle handle, AESCCM_SegmentedFinalizeOperation *operation)
1970 {
1971     DebugP_assert(handle);
1972     DebugP_assert(operation);
1973 
1974     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
1975 
1976 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
1977     if (object->common.key.encoding == CryptoKey_PLAINTEXT_HSM)
1978     {
1979         return AESCCMLPF3HSM_finalizeDecrypt(handle, operation);
1980     }
1981 #endif
1982 
1983     int_fast16_t status;
1984 
1985     status = AESCCMLPF3_performFinalizeChecks(object, operation);
1986 
1987     if (status != AESCCM_STATUS_SUCCESS)
1988     {
1989         return status;
1990     }
1991 
1992     if (operation->inputLength > 0U)
1993     {
1994         object->mac       = operation->mac;
1995         object->macLength = operation->macLength;
1996 
1997         status = AESCCMLPF3_addData(handle,
1998                                     AESCCM_OP_TYPE_FINALIZE_DECRYPT,
1999                                     (AESCCM_OperationUnion *)operation,
2000                                     operation->input,
2001                                     operation->output,
2002                                     operation->inputLength);
2003     }
2004 
2005     if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_POLLING) ||
2006         (operation->inputLength < AESCCMLPF3_DMA_SIZE_THRESHOLD))
2007     {
2008         if (status == AESCCM_STATUS_SUCCESS)
2009         {
2010             /* Perform a constant time comparision of the calculated MAC and the decrypted MAC */
2011             bool macValid = CryptoUtils_buffersMatch(object->intermediateTag,
2012                                                      operation->mac,
2013                                                      (size_t)operation->macLength);
2014 
2015             if (!macValid)
2016             {
2017                 status = AESCCM_STATUS_MAC_INVALID;
2018             }
2019         }
2020         else
2021         {
2022             object->common.returnStatus = status;
2023         }
2024 
2025         AESCommonLPF3_clearOperationInProgress(&object->common);
2026 
2027         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
2028         {
2029             object->callbackFxn(handle, status, (AESCCM_OperationUnion *)operation, AESCCM_OP_TYPE_FINALIZE_DECRYPT);
2030 
2031             /* Always return success in callback mode */
2032             status = AESCCM_STATUS_SUCCESS;
2033         }
2034     }
2035 
2036     return status;
2037 }
2038 
2039 /*
2040  *  ======== AESCCMLPF3_performFinalizeChecks ========
2041  */
AESCCMLPF3_performFinalizeChecks(const AESCCMLPF3_Object * object,const AESCCM_SegmentedFinalizeOperation * operation)2042 static int_fast16_t AESCCMLPF3_performFinalizeChecks(const AESCCMLPF3_Object *object,
2043                                                      const AESCCM_SegmentedFinalizeOperation *operation)
2044 {
2045     /* This operation can be called after setupXXXX, addAAD, or addData */
2046     DebugP_assert((object->operationType == AESCCM_OP_TYPE_AAD_ENCRYPT) ||
2047                   (object->operationType == AESCCM_OP_TYPE_DATA_ENCRYPT));
2048 
2049     /* Don't continue the segmented operation if there
2050      * was an error or a cancellation.
2051      */
2052     if (object->common.returnStatus != AESCCM_STATUS_SUCCESS)
2053     {
2054         return object->common.returnStatus;
2055     }
2056 
2057 #if (AESCommonLPF3_UNALIGNED_IO_SUPPORT_ENABLE == 0)
2058     /* Check word-alignment of input & output pointers */
2059     if (!IS_WORD_ALIGNED(operation->input) || !IS_WORD_ALIGNED(operation->output))
2060     {
2061         return AESCCM_STATUS_UNALIGNED_IO_NOT_SUPPORTED;
2062     }
2063 #endif
2064 
2065     /* All AAD should be processed at this point in time. */
2066     if (object->aadBytesProcessed != object->totalAADLength)
2067     {
2068         return AESCCM_STATUS_ERROR;
2069     }
2070 
2071     /* Additional payload data can be passed in finalize */
2072     if (operation->inputLength != object->totalCBCMACLengthRemaining)
2073     {
2074         return AESCCM_STATUS_ERROR;
2075     }
2076 
2077     /* Check DMA xfer limit for blocking and callback modes */
2078     if ((object->common.returnBehavior != AES_RETURN_BEHAVIOR_POLLING) &&
2079         !AESCommonLPF3_isDMALengthValid(operation->input, operation->output, operation->inputLength))
2080     {
2081         return AESCCM_STATUS_ERROR;
2082     }
2083 
2084     return AESCCM_STATUS_SUCCESS;
2085 }
2086 
2087 /*
2088  *  ======== AESCCM_cancelOperation ========
2089  */
AESCCM_cancelOperation(AESCCM_Handle handle)2090 int_fast16_t AESCCM_cancelOperation(AESCCM_Handle handle)
2091 {
2092     DebugP_assert(handle);
2093 
2094     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2095 
2096     /* Cancellation is only supported in callback mode */
2097     if (object->common.returnBehavior != AES_RETURN_BEHAVIOR_CALLBACK)
2098     {
2099         return AESCCM_STATUS_ERROR;
2100     }
2101 
2102     uintptr_t interruptKey = HwiP_disable();
2103 
2104     /* Return success if there is no active operation to cancel.
2105      * Do not execute the callback as it would have been executed already
2106      * when the operation completed.
2107      */
2108 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
2109     if (((object->common.key.encoding & CRYPTOKEY_HSM) == 0) && (!object->common.operationInProgress))
2110 #else
2111     if (!object->common.operationInProgress)
2112 #endif
2113     {
2114         HwiP_restore(interruptKey);
2115     }
2116     else
2117     {
2118         HwiP_restore(interruptKey);
2119 
2120         /* Cancel DMA for input and output channels, clear operation in-progress,
2121          * and releases crypto resource if necessary.
2122          */
2123         AESCommonLPF3_cancelOperation(&object->common, true);
2124 
2125 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
2126         /* Since the HSM cannot cancel an in-progress token, we must wait for the result to allow for
2127          * subsequent token submissions to succeed.
2128          */
2129         (void)HSMLPF3_cancelOperation();
2130 
2131         object->segmentedOperationInProgress = false;
2132 
2133         int_fast16_t status = AESCCMLPF3HSM_freeTempAssetID(handle);
2134         if (status != AESCCM_STATUS_SUCCESS)
2135         {
2136             return AESCCM_STATUS_ERROR;
2137         }
2138 #endif
2139 
2140         /* Operation pointer could be NULL if a segmented operation was setup
2141          * but neither AESCCM_addData or AESCCM_finalize was called.
2142          */
2143         if ((object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK) && (object->operation != NULL))
2144         {
2145             /* Call the callback function provided by the application */
2146             object->callbackFxn(handle, AESCCM_STATUS_CANCELED, object->operation, object->operationType);
2147         }
2148     }
2149 
2150     (void)memset(object->output, 0, object->totalDataLength);
2151 
2152     object->aad       = NULL;
2153     object->input     = NULL;
2154     object->output    = NULL;
2155     object->nonce     = NULL;
2156     object->mac       = NULL;
2157     object->operation = NULL;
2158 
2159     object->inputLength                = 0;
2160     object->totalCBCMACLengthRemaining = 0;
2161     object->totalCTRLengthRemaining    = 0;
2162     object->totalAADLength             = 0;
2163     object->totalDataLength            = 0;
2164     object->aadBytesProcessed          = 0;
2165 
2166     object->macLength   = 0;
2167     object->nonceLength = 0;
2168 
2169     return AESCCM_STATUS_SUCCESS;
2170 }
2171 
2172 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
2173 
2174 /*
2175  *  ======== AESCCMLPF3HSM_setMac ========
2176  */
AESCCMLPF3HSM_setMac(AESCCM_Handle handle,const uint8_t * mac,size_t macLength)2177 int_fast16_t AESCCMLPF3HSM_setMac(AESCCM_Handle handle, const uint8_t *mac, size_t macLength)
2178 {
2179     DebugP_assert(handle);
2180     DebugP_assert(nonce);
2181 
2182     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2183 
2184     /* This function cannot be called after addXXX() or finalizeXXX() */
2185     DebugP_assert((object->operationType == AESCCM_OPERATION_TYPE_DECRYPT) ||
2186                   (object->operationType == AESCCM_OPERATION_TYPE_ENCRYPT));
2187 
2188     /* Don't continue the segmented operation if there
2189      * was an error during setup.
2190      */
2191     if (object->common.returnStatus != AESCCM_STATUS_SUCCESS)
2192     {
2193         return object->common.returnStatus;
2194     }
2195 
2196     object->mac       = (uint8_t *)mac;
2197     object->macLength = (uint8_t)macLength;
2198 
2199     return AESCCM_STATUS_SUCCESS;
2200 }
2201 
2202 /*
2203  *  ======== AESCCMLPF3HSM_createAssetPostProcessing ========
2204  */
AESCCMLPF3HSM_createAssetPostProcessing(uintptr_t arg0)2205 static inline void AESCCMLPF3HSM_createAssetPostProcessing(uintptr_t arg0)
2206 {
2207     AESCCM_Handle handle      = (AESCCM_Handle)arg0;
2208     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2209     int_fast16_t status       = AESCCM_STATUS_ERROR;
2210     int8_t tokenResult        = HSMLPF3_getResultCode() & HSMLPF3_RETVAL_MASK;
2211 
2212     if (tokenResult == EIP130TOKEN_RESULT_SUCCESS)
2213     {
2214         object->tempAssetID = HSMLPF3_getResultAssetID();
2215         status              = AESCCM_STATUS_SUCCESS;
2216     }
2217 
2218     object->common.returnStatus = status;
2219 
2220     HSMLPF3_releaseLock();
2221 
2222     Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2223 }
2224 
2225 /*
2226  *  ======== AESCCMLPF3HSM_createTempAssetID ========
2227  */
AESCCMLPF3HSM_createTempAssetID(AESCCM_Handle handle,AESCCM_Mode direction)2228 static int_fast16_t AESCCMLPF3HSM_createTempAssetID(AESCCM_Handle handle, AESCCM_Mode direction)
2229 {
2230     int_fast16_t status       = AESCCM_STATUS_ERROR;
2231     int_fast16_t hsmRetval    = HSMLPF3_STATUS_ERROR;
2232     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2233     uint64_t assetPolicy      = 0U;
2234 
2235     if (!HSMLPF3_acquireLock(SemaphoreP_NO_WAIT, (uintptr_t)handle))
2236     {
2237         return AESCCM_STATUS_RESOURCE_UNAVAILABLE;
2238     }
2239     Power_setConstraint(PowerLPF3_DISALLOW_STANDBY);
2240 
2241     /* Lower 16-bit */
2242     assetPolicy |= EIP130_ASSET_POLICY_MODIFIABLE;
2243     assetPolicy |= EIP130_ASSET_POLICY_SOURCESECURE;
2244     assetPolicy |= EIP130_ASSET_POLICY_NOTCROSSDOMAIN;
2245     assetPolicy |= EIP130_ASSET_POLICY_PRIVATEDATA;
2246     assetPolicy |= EIP130_ASSET_POLICY_TEMPORARY;
2247     assetPolicy |= EIP130_ASSET_POLICY_SYMCRYPTO;
2248 
2249     /* Upper 16-bit */
2250     assetPolicy |= EIP130_ASSET_POLICY_SCUICIPHERAUTH;
2251     if (direction == AESCCM_MODE_DECRYPT)
2252     {
2253         assetPolicy |= EIP130_ASSET_POLICY_SCDIRDECVRFY;
2254     }
2255     else
2256     {
2257         assetPolicy |= EIP130_ASSET_POLICY_SCDIRENCGEN;
2258     }
2259     assetPolicy |= EIP130_ASSET_POLICY_SCACAES;
2260 
2261     HSMLPF3_constructCreateAssetToken(assetPolicy, KEY_TEMP_ASSET_SIZE);
2262 
2263     hsmRetval = HSMLPF3_submitToken(HSMLPF3_RETURN_BEHAVIOR_POLLING,
2264                                     AESCCMLPF3HSM_createAssetPostProcessing,
2265                                     (uintptr_t)handle);
2266     if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2267     {
2268         hsmRetval = HSMLPF3_waitForResult();
2269 
2270         if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2271         {
2272             status = object->common.returnStatus;
2273         }
2274     }
2275 
2276     if (hsmRetval != HSMLPF3_STATUS_SUCCESS)
2277     {
2278         Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2279 
2280         HSMLPF3_releaseLock();
2281     }
2282     return status;
2283 }
2284 
2285 /*
2286  *  ======== AESCCMLPF3HSM_oneStepPostProcessing ========
2287  */
AESCCMLPF3HSM_oneStepPostProcessing(uintptr_t arg0)2288 static inline void AESCCMLPF3HSM_oneStepPostProcessing(uintptr_t arg0)
2289 {
2290     AESCCM_Handle handle                      = (AESCCM_Handle)arg0;
2291     AESCCMLPF3_Object *object                 = AESCCMLPF3_getObject(handle);
2292     AESCCM_OneStepOperation *oneStepOperation = (AESCCM_OneStepOperation *)object->operation;
2293     int_fast16_t status                       = AESCCM_STATUS_ERROR;
2294     int32_t physicalResult                    = HSMLPF3_getResultCode();
2295     int8_t tokenResult                        = physicalResult & HSMLPF3_RETVAL_MASK;
2296 
2297     /* The HSM IP will throw an error when operation->macLength is zero despite it producing a correct
2298      * ciphertext/plaintext for both encrypt/decrypt operations and will compute a mac anyways.
2299      */
2300     if ((tokenResult == EIP130TOKEN_RESULT_INVALID_LENGTH) && (oneStepOperation->macLength == 0U))
2301     {
2302         tokenResult = EIP130TOKEN_RESULT_SUCCESS;
2303     }
2304 
2305     if (tokenResult == EIP130TOKEN_RESULT_SUCCESS)
2306     {
2307         if (object->operationType == AESCCM_OP_TYPE_ONESTEP_ENCRYPT)
2308         {
2309             HSMLPF3_getAESEncryptTag((void *)&oneStepOperation->mac[0]);
2310         }
2311 
2312         status = AESCCM_STATUS_SUCCESS;
2313     }
2314     else if ((object->operationType == AESCCM_OP_TYPE_ONESTEP_DECRYPT) ||
2315              (tokenResult == EIP130TOKEN_RESULT_VERIFY_ERROR))
2316     {
2317         status = AESCCM_STATUS_MAC_INVALID;
2318     }
2319 
2320     object->common.returnStatus = status;
2321 
2322     HSMLPF3_releaseLock();
2323 
2324     Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2325 
2326     if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
2327     {
2328         object->callbackFxn(handle, object->common.returnStatus, object->operation, object->operationType);
2329     }
2330 }
2331 
2332 /*
2333  *  ======== AESCCLPF3HSM_processOneStepHSM ========
2334  */
AESCCMLPF3HSM_processOneStepOperation(AESCCM_Handle handle)2335 static inline int_fast16_t AESCCMLPF3HSM_processOneStepOperation(AESCCM_Handle handle)
2336 {
2337     int_fast16_t status       = AESCCM_STATUS_SUCCESS;
2338     int_fast16_t hsmRetval    = HSMLPF3_STATUS_ERROR;
2339     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2340 
2341     if (!HSMLPF3_acquireLock(SemaphoreP_NO_WAIT, (uintptr_t)handle))
2342     {
2343         return AESCCM_STATUS_RESOURCE_UNAVAILABLE;
2344     }
2345 
2346     Power_setConstraint(PowerLPF3_DISALLOW_STANDBY);
2347 
2348     HSMLPF3_constructAESCCMOneStepPhysicalToken(object);
2349 
2350     hsmRetval = HSMLPF3_submitToken((HSMLPF3_ReturnBehavior)object->common.returnBehavior,
2351                                     AESCCMLPF3HSM_oneStepPostProcessing,
2352                                     (uintptr_t)handle);
2353     if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2354     {
2355         hsmRetval = HSMLPF3_waitForResult();
2356 
2357         if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2358         {
2359             status = object->common.returnStatus;
2360         }
2361     }
2362 
2363     if (hsmRetval != HSMLPF3_STATUS_SUCCESS)
2364     {
2365         Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2366 
2367         HSMLPF3_releaseLock();
2368     }
2369 
2370     return status;
2371 }
2372 
2373 /*
2374  *  ======== AESCCMLPF3HSM_oneStepOperation ========
2375  */
AESCCMLPF3HSM_oneStepOperation(AESCCM_Handle handle,AESCCM_OneStepOperation * operation,AESCCM_OperationType operationType)2376 static int_fast16_t AESCCMLPF3HSM_oneStepOperation(AESCCM_Handle handle,
2377                                                    AESCCM_OneStepOperation *operation,
2378                                                    AESCCM_OperationType operationType)
2379 {
2380     DebugP_assert(handle);
2381     DebugP_assert(operation);
2382     DebugP_assert(operation->key);
2383     /* Internally generated nonces aren't supported for now */
2384     DebugP_assert(!operation->nonceInternallyGenerated);
2385     DebugP_assert(operation->nonce && (operation->nonceLength >= 7U) && (operation->nonceLength <= 13U));
2386     DebugP_assert((operation->aad && (operation->aadLength > 0U)) ||
2387                   (operation->input && (operation->inputLength > 0U)));
2388     DebugP_assert(operation->mac && (operation->macLength <= 16U));
2389     /* Implementation only supports aadLength to 65,279 bytes */
2390     DebugP_assert(operation->aadLength <= B1_AAD_LENGTH_SMALL_LIMIT);
2391 
2392     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2393 
2394     /* The nonce length must be 7 to 13 bytes long */
2395     if ((operation->nonceLength < (uint8_t)7U) || (operation->nonceLength > (uint8_t)13U))
2396     {
2397         return AESCCM_STATUS_ERROR;
2398     }
2399 
2400     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
2401     if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
2402     {
2403         return AESCCM_STATUS_ERROR;
2404     }
2405 
2406     /* The combined length of AAD and payload data must be non-zero. */
2407     if ((operation->aadLength + operation->inputLength) == 0U)
2408     {
2409         return AESCCM_STATUS_ERROR;
2410     }
2411 
2412     /* A segmented operation may have been started but not finalized yet */
2413     if (object->segmentedOperationInProgress)
2414     {
2415         return AESCCM_STATUS_ERROR;
2416     }
2417 
2418     object->common.returnStatus = AESCCM_STATUS_SUCCESS;
2419 
2420     object->operation     = (AESCCM_OperationUnion *)operation;
2421     object->operationType = operationType;
2422 
2423     object->common.key = *(operation->key);
2424     object->input      = operation->input;
2425     object->output     = operation->output;
2426     object->mac        = operation->mac;
2427     object->aad        = operation->aad;
2428     object->nonce      = operation->nonce;
2429 
2430     object->inputLength     = operation->inputLength;
2431     object->totalDataLength = operation->inputLength;
2432     object->macLength       = operation->macLength;
2433     object->aadLength       = object->totalAADLength;
2434     object->totalAADLength  = operation->aadLength;
2435     object->nonceLength     = operation->nonceLength;
2436 
2437     object->totalDataLengthRemaining = object->totalDataLength;
2438     object->totalAADLengthRemaining  = object->totalAADLength;
2439 
2440     object->tempAssetID = 0U;
2441 
2442     /* Process all one-step operations with data length less than the DMA size
2443      * threshold as a polling mode operation.
2444      */
2445     return AESCCMLPF3HSM_processOneStepOperation(handle);
2446 }
2447 
2448 /*
2449  *  ======== AESCCMLPF3HSM_setupSegmentedOperation ========
2450  */
AESCCMLPF3HSM_setupSegmentedOperation(AESCCMLPF3_Object * object,const CryptoKey * key,size_t totalAADLength,size_t totalDataLength,size_t macLength)2451 static int_fast16_t AESCCMLPF3HSM_setupSegmentedOperation(AESCCMLPF3_Object *object,
2452                                                           const CryptoKey *key,
2453                                                           size_t totalAADLength,
2454                                                           size_t totalDataLength,
2455                                                           size_t macLength)
2456 {
2457     DebugP_assert(key);
2458 
2459     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
2460     if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
2461     {
2462         return AESCCM_STATUS_ERROR;
2463     }
2464 
2465     /* A segmented operation may have been started but not finalized yet */
2466     if (object->segmentedOperationInProgress)
2467     {
2468         return AESCCM_STATUS_ERROR;
2469     }
2470 
2471     /* Make internal copy of crypto key */
2472     object->common.key = *key;
2473 
2474     /* returnStatus is only changed in the case of an error or cancellation */
2475     object->common.returnStatus = AES_STATUS_SUCCESS;
2476 
2477     object->segmentedOperationInProgress = true;
2478 
2479     /* If the user doesn't provide the total lengths in the setupXXXX()
2480      * calls, they must provide the lengths in setLengths().
2481      */
2482     object->totalAADLength  = totalAADLength;
2483     object->totalDataLength = totalDataLength;
2484     object->macLength       = (uint8_t)macLength;
2485 
2486     object->totalCTRLengthRemaining    = totalDataLength;
2487     object->totalCBCMACLengthRemaining = totalDataLength;
2488     object->aadBytesProcessed          = 0U;
2489     object->bufferedAADLength          = (uint8_t)0U;
2490 
2491     object->totalDataLengthRemaining = totalDataLength;
2492     object->totalAADLengthRemaining  = totalAADLength;
2493     object->inputLength              = 0U;
2494     object->aadLength                = 0U;
2495 
2496     /* Initialize MAC pointer to NULL to avoid premature processing of the
2497      * MAC in the ISR.
2498      */
2499     object->mac = NULL;
2500 
2501     /* Initialize operation pointer to NULL in case AESCCM_cancelOperation
2502      * is called after AESCCM_setupXXXX and callback should be skipped.
2503      */
2504     object->operation = NULL;
2505 
2506     return AESCCM_STATUS_SUCCESS;
2507 }
2508 
2509 /*
2510  *  ======== AESCCMLPF3HSM_setupEncrypt ========
2511  */
AESCCMLPF3HSM_setupEncrypt(AESCCM_Handle handle,const CryptoKey * key,size_t totalAADLength,size_t totalPlaintextLength,size_t macLength)2512 int_fast16_t AESCCMLPF3HSM_setupEncrypt(AESCCM_Handle handle,
2513                                         const CryptoKey *key,
2514                                         size_t totalAADLength,
2515                                         size_t totalPlaintextLength,
2516                                         size_t macLength)
2517 {
2518     DebugP_assert(handle);
2519     int_fast16_t status       = AESCCM_STATUS_ERROR;
2520     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2521 
2522     status = AESCCMLPF3HSM_setupSegmentedOperation(object, key, totalAADLength, totalPlaintextLength, macLength);
2523     if (status == AESCCM_STATUS_SUCCESS)
2524     {
2525         object->operationType = AESCCM_OPERATION_TYPE_ENCRYPT;
2526         status                = AESCCMLPF3HSM_createTempAssetID(handle, AESCCM_MODE_ENCRYPT);
2527     }
2528 
2529     return status;
2530 }
2531 
2532 /*
2533  *  ======== AESCCMLPF3HSM_setupDecrypt ========
2534  */
AESCCMLPF3HSM_setupDecrypt(AESCCM_Handle handle,const CryptoKey * key,size_t totalAADLength,size_t totalPlaintextLength,size_t macLength)2535 int_fast16_t AESCCMLPF3HSM_setupDecrypt(AESCCM_Handle handle,
2536                                         const CryptoKey *key,
2537                                         size_t totalAADLength,
2538                                         size_t totalPlaintextLength,
2539                                         size_t macLength)
2540 {
2541     DebugP_assert(handle);
2542     int_fast16_t status       = AESCCM_STATUS_ERROR;
2543     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2544 
2545     status = AESCCMLPF3HSM_setupSegmentedOperation(object, key, totalAADLength, totalPlaintextLength, macLength);
2546     if (status == AESCCM_STATUS_SUCCESS)
2547     {
2548         object->operationType = AESCCM_OPERATION_TYPE_DECRYPT;
2549         status                = AESCCMLPF3HSM_createTempAssetID(handle, AESCCM_MODE_DECRYPT);
2550     }
2551 
2552     return status;
2553 }
2554 
2555 /*
2556  *  ======== AESCCMLPF3HSM_SegmentedPostProcessing ========
2557  */
AESCCMLPF3HSM_SegmentedPostProcessing(uintptr_t arg0)2558 static inline void AESCCMLPF3HSM_SegmentedPostProcessing(uintptr_t arg0)
2559 {
2560     AESCCM_Handle handle      = (AESCCM_Handle)arg0;
2561     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2562     int_fast16_t status       = AESCCM_STATUS_ERROR;
2563     AESCCM_Mode direction     = AESCCM_MODE_ENCRYPT;
2564     int32_t physicalResult    = HSMLPF3_getResultCode();
2565     int8_t tokenResult        = physicalResult & HSMLPF3_RETVAL_MASK;
2566 
2567     /* The HSM IP will throw an error when operation->macLength is zero despite it producing a correct
2568      * ciphertext/plaintext for both encrypt/decrypt operations and will compute a mac anyways.
2569      */
2570     if ((tokenResult == EIP130TOKEN_RESULT_INVALID_LENGTH) && (object->macLength == 0U))
2571     {
2572         tokenResult = EIP130TOKEN_RESULT_SUCCESS;
2573     }
2574 
2575     if ((object->operationType == AESCCM_OP_TYPE_DATA_DECRYPT) ||
2576         (object->operationType == AESCCM_OP_TYPE_FINALIZE_DECRYPT))
2577     {
2578         direction = AESCCM_MODE_DECRYPT;
2579     }
2580 
2581     if ((object->operationType == AESCCM_OP_TYPE_AAD_ENCRYPT) || (object->operationType == AESCCM_OP_TYPE_AAD_DECRYPT))
2582     {
2583         if (tokenResult == EIP130TOKEN_RESULT_SUCCESS)
2584         {
2585             object->totalAADLengthRemaining -= object->aadLength;
2586             object->aadLength = 0U;
2587 
2588             status = AESCCM_STATUS_SUCCESS;
2589         }
2590     }
2591     else
2592     {
2593         if (tokenResult == EIP130TOKEN_RESULT_SUCCESS)
2594         {
2595             object->totalAADLengthRemaining -= object->aadLength;
2596             object->totalDataLengthRemaining -= object->inputLength;
2597 
2598             if (direction == AESCCM_MODE_ENCRYPT)
2599             {
2600                 HSMLPF3_getAESEncryptTag((uint8_t *)&object->intermediateTag[0]);
2601 
2602                 if ((object->operationType == AESCCM_OP_TYPE_FINALIZE_ENCRYPT) &&
2603                     ((object->totalDataLengthRemaining == 0U) && (object->totalAADLengthRemaining == 0U)))
2604                 {
2605                     (void)memcpy((void *)&object->mac[0], (void *)&object->intermediateTag[0], object->macLength);
2606                 }
2607             }
2608 
2609             status = AESCCM_STATUS_SUCCESS;
2610         }
2611         else if ((tokenResult == EIP130TOKEN_RESULT_VERIFY_ERROR) &&
2612                  (object->operationType == AESCCM_OP_TYPE_FINALIZE_DECRYPT))
2613         {
2614             object->totalAADLengthRemaining -= object->aadLength;
2615             object->totalDataLengthRemaining -= object->inputLength;
2616 
2617             status = AESCCM_STATUS_MAC_INVALID;
2618         }
2619     }
2620 
2621     Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2622 
2623     HSMLPF3_releaseLock();
2624 
2625     if ((object->operationType == AESCCM_OP_TYPE_FINALIZE_ENCRYPT) ||
2626         (object->operationType == AESCCM_OP_TYPE_FINALIZE_DECRYPT))
2627     {
2628         status = AESCCMLPF3HSM_freeTempAssetID(handle);
2629 
2630         object->segmentedOperationInProgress = false;
2631     }
2632 
2633     object->common.returnStatus = status;
2634 
2635     if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
2636     {
2637         object->callbackFxn(handle, status, object->operation, object->operationType);
2638     }
2639 }
2640 
2641 /*
2642  *  ======== AESCCMLPF3HSM_addAAD ========
2643  */
AESCCMLPF3HSM_addAAD(AESCCM_Handle handle,AESCCM_SegmentedAADOperation * operation)2644 int_fast16_t AESCCMLPF3HSM_addAAD(AESCCM_Handle handle, AESCCM_SegmentedAADOperation *operation)
2645 {
2646     DebugP_assert(handle);
2647     DebugP_assert(operation);
2648 
2649     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2650     int_fast16_t status       = AESCCM_STATUS_SUCCESS;
2651     int_fast16_t hsmRetval    = HSMLPF3_STATUS_ERROR;
2652 
2653     object->operation = (AESCCM_OperationUnion *)operation;
2654 
2655     if (object->totalAADLengthRemaining == object->totalAADLength)
2656     {
2657         object->aad = operation->aad;
2658     }
2659 
2660     /* Don't continue the segmented operation if there
2661      * was an error or a cancellation.
2662      */
2663     if (object->common.returnStatus != AESCCM_STATUS_SUCCESS)
2664     {
2665         return object->common.returnStatus;
2666     }
2667 
2668     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
2669     if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
2670     {
2671         return AESCCM_STATUS_ERROR;
2672     }
2673 
2674     if (!HSMLPF3_acquireLock(SemaphoreP_NO_WAIT, (uintptr_t)handle))
2675     {
2676         return AESCCM_STATUS_RESOURCE_UNAVAILABLE;
2677     }
2678 
2679     Power_setConstraint(PowerLPF3_DISALLOW_STANDBY);
2680 
2681     /* This operation can be called after setup or after addAAD again. */
2682     DebugP_assert((object->operationType == AESCCM_OPERATION_TYPE_DECRYPT) ||
2683                   (object->operationType == AESCCM_OPERATION_TYPE_ENCRYPT) ||
2684                   (object->operationType == AESCCM_OP_TYPE_AAD_DECRYPT) ||
2685                   (object->operationType == AESCCM_OP_TYPE_AAD_ENCRYPT));
2686 
2687     uint8_t aadBytesProcessed = object->totalAADLength - object->totalAADLengthRemaining;
2688     size_t calcAADLen         = aadBytesProcessed + operation->aadLength;
2689 
2690     /* The total AAD input length must not exceed the total length specified
2691      * in AESCCM_setLengths() or the setupXXXX() call.
2692      */
2693     if (calcAADLen > object->totalAADLength)
2694     {
2695         status = AESCCM_STATUS_ERROR;
2696     }
2697 
2698     if (status == AESCCM_STATUS_ERROR)
2699     {
2700         Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2701 
2702         HSMLPF3_releaseLock();
2703 
2704         return status;
2705     }
2706 
2707     AESCCM_OperationType operationType = AESCCM_OP_TYPE_AAD_ENCRYPT;
2708 
2709     if ((object->operationType == AESCCM_OPERATION_TYPE_DECRYPT) ||
2710         (object->operationType == AESCCM_OP_TYPE_AAD_DECRYPT))
2711     {
2712         operationType = AESCCM_OP_TYPE_AAD_DECRYPT;
2713     }
2714 
2715     object->operationType = operationType;
2716 
2717     uint8_t aadBytesToProcess = operation->aadLength;
2718     uint8_t inputRemainder    = aadBytesToProcess % AES_BLOCK_SIZE;
2719 
2720     if (inputRemainder > 0U)
2721     {
2722         aadBytesToProcess -= inputRemainder;
2723     }
2724 
2725     if (aadBytesProcessed + aadBytesToProcess == object->totalAADLength)
2726     {
2727         aadBytesToProcess -= AES_BLOCK_SIZE;
2728     }
2729 
2730     object->aadLength   = aadBytesToProcess;
2731     object->inputLength = 0U;
2732 
2733     if (aadBytesToProcess > 0U)
2734     {
2735         HSMLPF3_constructAESCCMSegmentedAADPhysicalToken(object);
2736 
2737         hsmRetval = HSMLPF3_submitToken((HSMLPF3_ReturnBehavior)object->common.returnBehavior,
2738                                         AESCCMLPF3HSM_SegmentedPostProcessing,
2739                                         (uintptr_t)handle);
2740         if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2741         {
2742             hsmRetval = HSMLPF3_waitForResult();
2743 
2744             if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2745             {
2746                 status = object->common.returnStatus;
2747             }
2748         }
2749 
2750         if (hsmRetval != HSMLPF3_STATUS_SUCCESS)
2751         {
2752             Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2753 
2754             HSMLPF3_releaseLock();
2755         }
2756 
2757         object->common.returnStatus = status;
2758     }
2759     else
2760     {
2761         Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2762 
2763         HSMLPF3_releaseLock();
2764 
2765         object->common.returnStatus = status;
2766 
2767         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
2768         {
2769             object->callbackFxn(handle, status, (AESCCM_OperationUnion *)operation, operationType);
2770 
2771             /* Always return success in callback mode */
2772             status = AESCCM_STATUS_SUCCESS;
2773         }
2774     }
2775 
2776     return status;
2777 }
2778 
2779 /*
2780  *  ======== AESCCMLPF3HSM_addData ========
2781  */
AESCCMLPF3HSM_addData(AESCCM_Handle handle,AESCCM_OperationType operationType,AESCCM_OperationUnion * operation,const uint8_t * input,uint8_t * output,size_t inputLength)2782 static int_fast16_t AESCCMLPF3HSM_addData(AESCCM_Handle handle,
2783                                           AESCCM_OperationType operationType,
2784                                           AESCCM_OperationUnion *operation,
2785                                           const uint8_t *input,
2786                                           uint8_t *output,
2787                                           size_t inputLength)
2788 {
2789     int_fast16_t status                               = AESCCM_STATUS_SUCCESS;
2790     int_fast16_t hsmRetval                            = HSMLPF3_STATUS_ERROR;
2791     AESCCMLPF3_Object *object                         = AESCCMLPF3_getObject(handle);
2792     AESCCM_SegmentedDataOperation *segmentedOperation = (AESCCM_SegmentedDataOperation *)operation;
2793 
2794     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
2795     if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
2796     {
2797         return AESCCM_STATUS_ERROR;
2798     }
2799 
2800     if (!HSMLPF3_acquireLock(SemaphoreP_NO_WAIT, (uintptr_t)handle))
2801     {
2802         return AESCCM_STATUS_RESOURCE_UNAVAILABLE;
2803     }
2804 
2805     Power_setConstraint(PowerLPF3_DISALLOW_STANDBY);
2806 
2807     object->operationType = operationType;
2808     object->operation     = operation;
2809 
2810     if (object->totalDataLengthRemaining == object->totalDataLength)
2811     {
2812         object->input  = segmentedOperation->input;
2813         object->output = segmentedOperation->output;
2814     }
2815 
2816     object->aadLength   = object->totalAADLengthRemaining;
2817     object->inputLength = inputLength;
2818 
2819     HSMLPF3_constructAESCCMSegmentedDataPhysicalToken(object);
2820 
2821     hsmRetval = HSMLPF3_submitToken((HSMLPF3_ReturnBehavior)object->common.returnBehavior,
2822                                     AESCCMLPF3HSM_SegmentedPostProcessing,
2823                                     (uintptr_t)handle);
2824     if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2825     {
2826         hsmRetval = HSMLPF3_waitForResult();
2827 
2828         if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2829         {
2830             status = object->common.returnStatus;
2831         }
2832     }
2833 
2834     if (hsmRetval != HSMLPF3_STATUS_SUCCESS)
2835     {
2836         Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2837 
2838         HSMLPF3_releaseLock();
2839     }
2840 
2841     object->common.returnStatus = status;
2842 
2843     return status;
2844 }
2845 
2846 /*
2847  *  ======== AESCCMLPF3HSM_freeAssetPostProcessing ========
2848  */
AESCCMLPF3HSM_freeAssetPostProcessing(uintptr_t arg0)2849 static inline void AESCCMLPF3HSM_freeAssetPostProcessing(uintptr_t arg0)
2850 {
2851     AESCCM_Handle handle      = (AESCCM_Handle)arg0;
2852     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2853     int_fast16_t status       = AESCCM_STATUS_ERROR;
2854     int8_t tokenResult        = HSMLPF3_getResultCode() & HSMLPF3_RETVAL_MASK;
2855 
2856     if (tokenResult == EIP130TOKEN_RESULT_SUCCESS)
2857     {
2858         object->tempAssetID = 0;
2859         status              = AESCCM_STATUS_SUCCESS;
2860     }
2861 
2862     object->common.returnStatus = status;
2863 
2864     if ((HSMLPF3_ReturnBehavior)object->common.returnBehavior == HSMLPF3_RETURN_BEHAVIOR_POLLING)
2865     {
2866         Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2867 
2868         HSMLPF3_releaseLock();
2869     }
2870 }
2871 
2872 /*
2873  *  ======== AESCCMLPF3HSM_freeTempAssetID ========
2874  */
AESCCMLPF3HSM_freeTempAssetID(AESCCM_Handle handle)2875 static int_fast16_t AESCCMLPF3HSM_freeTempAssetID(AESCCM_Handle handle)
2876 {
2877     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2878     int_fast16_t status       = AESCCM_STATUS_SUCCESS;
2879     int_fast16_t hsmRetval    = HSMLPF3_STATUS_ERROR;
2880 
2881     if (object->tempAssetID != 0)
2882     {
2883         if ((HSMLPF3_ReturnBehavior)object->common.returnBehavior == HSMLPF3_RETURN_BEHAVIOR_POLLING)
2884         {
2885             if (!HSMLPF3_acquireLock(SemaphoreP_NO_WAIT, (uintptr_t)handle))
2886             {
2887                 return AESCCM_STATUS_RESOURCE_UNAVAILABLE;
2888             }
2889             Power_setConstraint(PowerLPF3_DISALLOW_STANDBY);
2890         }
2891 
2892         HSMLPF3_constructDeleteAssetToken(object->tempAssetID);
2893 
2894         hsmRetval = HSMLPF3_submitToken(HSMLPF3_RETURN_BEHAVIOR_POLLING,
2895                                         AESCCMLPF3HSM_freeAssetPostProcessing,
2896                                         (uintptr_t)handle);
2897         if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2898         {
2899             hsmRetval = HSMLPF3_waitForResult();
2900 
2901             if (hsmRetval == HSMLPF3_STATUS_SUCCESS)
2902             {
2903                 status = object->common.returnStatus;
2904             }
2905         }
2906     }
2907 
2908     if (((HSMLPF3_ReturnBehavior)object->common.returnBehavior == HSMLPF3_RETURN_BEHAVIOR_POLLING) &&
2909         (hsmRetval != HSMLPF3_STATUS_SUCCESS))
2910     {
2911         Power_releaseConstraint(PowerLPF3_DISALLOW_STANDBY);
2912 
2913         HSMLPF3_releaseLock();
2914     }
2915 
2916     return status;
2917 }
2918 
2919 /*
2920  *  ======== AESCCMLPF3HSM_finalizeEncrypt ========
2921  */
AESCCMLPF3HSM_finalizeEncrypt(AESCCM_Handle handle,AESCCM_SegmentedFinalizeOperation * operation)2922 int_fast16_t AESCCMLPF3HSM_finalizeEncrypt(AESCCM_Handle handle, AESCCM_SegmentedFinalizeOperation *operation)
2923 {
2924     DebugP_assert(handle);
2925     DebugP_assert(operation);
2926 
2927     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2928     int_fast16_t status;
2929 
2930     status = AESCCMLPF3HSM_performFinalizeChecks(object, operation);
2931 
2932     if (status != AESCCM_STATUS_SUCCESS)
2933     {
2934         return status;
2935     }
2936 
2937     if (object->totalDataLengthRemaining == object->totalDataLength)
2938     {
2939         object->input  = operation->input;
2940         object->output = operation->output;
2941     }
2942 
2943     object->mac       = operation->mac;
2944     object->macLength = operation->macLength;
2945 
2946     if ((operation->inputLength > 0U) || (object->totalAADLengthRemaining > 0))
2947     {
2948         status = AESCCMLPF3HSM_addData(handle,
2949                                        AESCCM_OP_TYPE_FINALIZE_ENCRYPT,
2950                                        (AESCCM_OperationUnion *)operation,
2951                                        operation->input,
2952                                        operation->output,
2953                                        operation->inputLength);
2954     }
2955     else
2956     {
2957         (void)memcpy(operation->mac, (uint32_t *)&object->intermediateTag[0], operation->macLength);
2958 
2959         status = AESCCMLPF3HSM_freeTempAssetID(handle);
2960 
2961         object->segmentedOperationInProgress = false;
2962 
2963         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
2964         {
2965             object->callbackFxn(handle, status, (AESCCM_OperationUnion *)operation, AESCCM_OP_TYPE_FINALIZE_ENCRYPT);
2966         }
2967     }
2968     return status;
2969 }
2970 
2971 /*
2972  *  ======== AESCCMLPF3HSM_finalizeDecrypt ========
2973  */
AESCCMLPF3HSM_finalizeDecrypt(AESCCM_Handle handle,AESCCM_SegmentedFinalizeOperation * operation)2974 int_fast16_t AESCCMLPF3HSM_finalizeDecrypt(AESCCM_Handle handle, AESCCM_SegmentedFinalizeOperation *operation)
2975 {
2976     DebugP_assert(handle);
2977     DebugP_assert(operation);
2978 
2979     AESCCMLPF3_Object *object = AESCCMLPF3_getObject(handle);
2980     int_fast16_t status;
2981 
2982     status = AESCCMLPF3HSM_performFinalizeChecks(object, operation);
2983 
2984     if (status != AESCCM_STATUS_SUCCESS)
2985     {
2986         return status;
2987     }
2988 
2989     if (object->totalDataLengthRemaining == object->totalDataLength)
2990     {
2991         object->input  = operation->input;
2992         object->output = operation->output;
2993     }
2994 
2995     object->mac       = operation->mac;
2996     object->macLength = operation->macLength;
2997 
2998     if ((operation->inputLength > 0U) || (object->totalAADLengthRemaining > 0U))
2999     {
3000         status = AESCCMLPF3HSM_addData(handle,
3001                                        AESCCM_OP_TYPE_FINALIZE_DECRYPT,
3002                                        (AESCCM_OperationUnion *)operation,
3003                                        operation->input,
3004                                        operation->output,
3005                                        operation->inputLength);
3006     }
3007     else
3008     {
3009         status = AESCCMLPF3HSM_freeTempAssetID(handle);
3010 
3011         object->segmentedOperationInProgress = false;
3012 
3013         if (object->common.returnBehavior == AES_RETURN_BEHAVIOR_CALLBACK)
3014         {
3015             object->callbackFxn(handle, status, (AESCCM_OperationUnion *)operation, AESCCM_OP_TYPE_FINALIZE_DECRYPT);
3016         }
3017     }
3018 
3019     return status;
3020 }
3021 
3022 /*
3023  *  ======== AESCCMLPF3HSM_performFinalizeChecks ========
3024  */
AESCCMLPF3HSM_performFinalizeChecks(const AESCCMLPF3_Object * object,const AESCCM_SegmentedFinalizeOperation * operation)3025 static int_fast16_t AESCCMLPF3HSM_performFinalizeChecks(const AESCCMLPF3_Object *object,
3026                                                         const AESCCM_SegmentedFinalizeOperation *operation)
3027 {
3028     /* This operation can be called after setupXXXX, addAAD, or addData */
3029     DebugP_assert((object->operationType == AESCCM_OP_TYPE_AAD_ENCRYPT) ||
3030                   (object->operationType == AESCCM_OP_TYPE_DATA_ENCRYPT));
3031 
3032     /* Don't continue the segmented operation if there
3033      * was an error or a cancellation.
3034      */
3035     if (object->common.returnStatus != AESCCM_STATUS_SUCCESS)
3036     {
3037         return object->common.returnStatus;
3038     }
3039 
3040     /* If the HSM IP and/or HSMSAL failed to boot then we cannot perform any HSM-related operation */
3041     if (object->hsmStatus != HSMLPF3_STATUS_SUCCESS)
3042     {
3043         return AESCCM_STATUS_ERROR;
3044     }
3045 
3046     /* Additional payload data can be passed in finalize */
3047     if (operation->inputLength != object->totalDataLengthRemaining)
3048     {
3049         return AESCCM_STATUS_ERROR;
3050     }
3051 
3052     return AESCCM_STATUS_SUCCESS;
3053 }
3054 
3055 #endif