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