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