1 /*
2 * Copyright 2020-2023 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_iped.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "platform.drivers.iped"
16 #endif
17 /*******************************************************************************
18 * Prototypes
19 ******************************************************************************/
20 static status_t IPED_ELS_check_key(uint8_t keyIdx, mcuxClEls_KeyProp_t *pKeyProp);
21 static status_t IPED_ELS_gen_iv_key(void);
22 static status_t IPED_ELS_enable(void);
23 static status_t IPED_ELS_calculate_iv(uint32_t *IvReg);
24 /*******************************************************************************
25 * Code
26 ******************************************************************************/
IPED_SetRegionAddressRange(FLEXSPI_Type * base,iped_region_t region,uint32_t start_address,uint32_t end_address)27 status_t IPED_SetRegionAddressRange(FLEXSPI_Type *base,
28 iped_region_t region,
29 uint32_t start_address,
30 uint32_t end_address)
31 {
32 status_t status = kStatus_Fail;
33
34 do
35 {
36 /* Check if region is not locked */
37 if ((base->IPEDCTXCTRL[1] & (FLEXSPI_IPEDCTXCTRLX_IPEDCTXCTRL_CTX0_FREEZE1_MASK << (region * 2u))) !=
38 (IPED_RW_ENABLE_VAL << (region * 2u)))
39 {
40 status = kStatus_IPED_RegionIsLocked;
41 break;
42 }
43
44 /* Disable soft lock for given region first */
45 base->IPEDCTXCTRL[0] =
46 (base->IPEDCTXCTRL[0] & ~(FLEXSPI_IPEDCTXCTRLX_IPEDCTXCTRL_CTX0_FREEZE0_MASK << (region * 2u))) |
47 (IPED_RW_ENABLE_VAL << (region * 2u));
48
49 switch (region)
50 {
51 case kIPED_Region0:
52 base->IPEDCTX0START = start_address;
53 base->IPEDCTX0END = end_address;
54 status = kStatus_Success;
55 break;
56
57 case kIPED_Region1:
58 base->IPEDCTX1START = start_address;
59 base->IPEDCTX1END = end_address;
60 status = kStatus_Success;
61 break;
62
63 case kIPED_Region2:
64 base->IPEDCTX2START = start_address;
65 base->IPEDCTX2END = end_address;
66 status = kStatus_Success;
67 break;
68
69 case kIPED_Region3:
70 base->IPEDCTX3START = start_address;
71 base->IPEDCTX3END = end_address;
72 status = kStatus_Success;
73 break;
74
75 default:
76 status = kStatus_InvalidArgument;
77 break;
78 }
79
80 /* Re-enable soft lock for given region */
81 base->IPEDCTXCTRL[0] =
82 (base->IPEDCTXCTRL[0] & ~(FLEXSPI_IPEDCTXCTRLX_IPEDCTXCTRL_CTX0_FREEZE0_MASK << (region * 2u))) |
83 (IPED_RW_DISABLE_VAL << (region * 2u));
84 } while (0);
85
86 return status;
87 }
88
IPED_GetRegionAddressRange(FLEXSPI_Type * base,iped_region_t region,uint32_t * start_address,uint32_t * end_address)89 status_t IPED_GetRegionAddressRange(FLEXSPI_Type *base,
90 iped_region_t region,
91 uint32_t *start_address,
92 uint32_t *end_address)
93 {
94 status_t status = kStatus_Fail;
95
96 switch (region)
97 {
98 case kIPED_Region0:
99 *start_address = base->IPEDCTX0START;
100 *end_address = base->IPEDCTX0END;
101 status = kStatus_Success;
102 break;
103
104 case kIPED_Region1:
105 *start_address = base->IPEDCTX1START;
106 *end_address = base->IPEDCTX1END;
107 status = kStatus_Success;
108 break;
109
110 case kIPED_Region2:
111 *start_address = base->IPEDCTX2START;
112 *end_address = base->IPEDCTX2END;
113 status = kStatus_Success;
114 break;
115
116 case kIPED_Region3:
117 *start_address = base->IPEDCTX3START;
118 *end_address = base->IPEDCTX3END;
119 status = kStatus_Success;
120 break;
121
122 default:
123 status = kStatus_InvalidArgument;
124 break;
125 }
126
127 return status;
128 }
129
IPED_SetRegionIV(FLEXSPI_Type * base,iped_region_t region,const uint8_t iv[8])130 status_t IPED_SetRegionIV(FLEXSPI_Type *base, iped_region_t region, const uint8_t iv[8])
131 {
132 status_t status = kStatus_Fail;
133
134 switch (region)
135 {
136 case kIPED_Region0:
137 base->IPEDCTX0IV0 = ((uint32_t *)(uintptr_t)iv)[0];
138 base->IPEDCTX0IV1 = ((uint32_t *)(uintptr_t)iv)[1];
139 status = kStatus_Success;
140 break;
141
142 case kIPED_Region1:
143 base->IPEDCTX1IV0 = ((uint32_t *)(uintptr_t)iv)[0];
144 base->IPEDCTX1IV1 = ((uint32_t *)(uintptr_t)iv)[1];
145 status = kStatus_Success;
146 break;
147
148 case kIPED_Region2:
149 base->IPEDCTX2IV0 = ((uint32_t *)(uintptr_t)iv)[0];
150 base->IPEDCTX2IV1 = ((uint32_t *)(uintptr_t)iv)[1];
151 status = kStatus_Success;
152 break;
153
154 case kIPED_Region3:
155 base->IPEDCTX3IV0 = ((uint32_t *)(uintptr_t)iv)[0];
156 base->IPEDCTX3IV1 = ((uint32_t *)(uintptr_t)iv)[1];
157 status = kStatus_Success;
158 break;
159
160 default:
161 status = kStatus_InvalidArgument;
162 break;
163 }
164
165 return status;
166 }
167
168 /*!
169 * @brief Configures IPED setting.
170 *
171 * This function does the initial IPED configuration via ROM IAP API call.
172 * IPED_SR_x configuration for each region configuration is stored into FFR (CMPA).
173 * IPED IV erase counters (MCTR_INT_IV_CTRx) in CFPA are updated accordingly.
174 *
175 * Note: This function is expected to be called once in the device lifetime,
176 * typically during the initial device provisioning (especially if programming the CMPA pages in PFR flash is enabled).
177 * Note: Disabling IPED can be only done via ISP/SB file commands provided before ROM boot execution.
178 * these commands will have to set IPED start & end addresses and ENABLE bits in CMPA page accordingly.
179 *
180 * @param coreCtx The pointer to the ROM API driver context structure.
181 * @param config The pointer to the IPED driver configuration structure.
182 * @param lock The CMPA IPEDx_START bits[1:0] 01 - Enabled, 10,11 - Enabled & locked
183 * @param writeCmpa If selected, IPED configuration will be programmed in PFR flash using ROM API. Note: This can not be
184 * reverted!!
185 *
186 * @retval #kStatus_Success
187 * @retval #kStatus_CommandUnsupported
188 * @retval #kStatus_InvalidArgument
189 * @retval #kStatus_FLASH_ModifyProtectedAreaDisallowed
190 * @retval #kStatusMemoryRangeInvalid
191 * @retval #kStatus_Fail
192 * @retval #kStatus_OutOfRange
193 * @retval #kStatus_SPI_BaudrateNotSupport
194 */
IPED_Configure(api_core_context_t * coreCtx,flexspi_iped_region_arg_t * config,iped_lock_t lock,iped_cmpa_t writeCmpa)195 status_t IPED_Configure(api_core_context_t *coreCtx,
196 flexspi_iped_region_arg_t *config,
197 iped_lock_t lock,
198 iped_cmpa_t writeCmpa)
199 {
200 status_t status = kStatus_Fail;
201 flash_config_t flash_config;
202 IPED_CMPA_page cmpa_buffer = {0};
203
204 /* Enable ELS and check keys */
205 if (kStatus_Success != IPED_ELS_enable())
206 {
207 return kStatus_Fail;
208 }
209
210 /* Check input argument */
211 if (((lock != kIPED_RegionLock) && (lock != kIPED_RegionUnlock)) ||
212 ((writeCmpa != kIPED_SkipCMPA) && (writeCmpa != kIPED_WriteCMPA)))
213 {
214 return kStatus_InvalidArgument;
215 }
216
217 /* Prepare IPED configuration structure */
218 uint32_t config_option_iped[3] = {(IPED_TAG << IPED_TAG_SHIFT) | config->option.iped_region, config->start,
219 config->end};
220
221 /* Configure IPED via ROM API, ROM API will provide config parameter check */
222 status = MEM_Config(coreCtx, config_option_iped, kMemoryFlexSpiNor);
223 if (status != kStatus_Success)
224 {
225 return kStatus_Fail;
226 }
227
228 if (writeCmpa == kIPED_WriteCMPA)
229 {
230 /* Clean up Flash driver structure and Init*/
231 memset(&flash_config, 0, sizeof(flash_config_t));
232 if (FLASH_Init(&flash_config) != kStatus_Success)
233 {
234 return kStatus_Fail;
235 }
236
237 /* FFR Init */
238 if (FFR_Init(&flash_config) != kStatus_Success)
239 {
240 return kStatus_Fail;
241 }
242
243 /* Read whole CMPA page */
244 status = FFR_GetCustomerData(&flash_config, (uint8_t *)&cmpa_buffer, 0u, CMPA_PAGE_SIZE);
245 if (kStatus_Success != status)
246 {
247 return kStatus_Fail;
248 }
249
250 switch (config->option.iped_region)
251 {
252 case kIPED_Region0:
253 cmpa_buffer.IPED0_START = (config->start & IPED_ADDRESS_MASK) | (lock & IPED_ENABLE_MASK);
254 cmpa_buffer.IPED0_END = config->end;
255 break;
256 case kIPED_Region1:
257 cmpa_buffer.IPED1_START = (config->start & IPED_ADDRESS_MASK) | (lock & IPED_ENABLE_MASK);
258 cmpa_buffer.IPED1_END = config->end;
259 break;
260 case kIPED_Region2:
261 cmpa_buffer.IPED2_START = (config->start & IPED_ADDRESS_MASK) | (lock & IPED_ENABLE_MASK);
262 cmpa_buffer.IPED2_END = config->end;
263 break;
264 case kIPED_Region3:
265 cmpa_buffer.IPED3_START = (config->start & IPED_ADDRESS_MASK) | (lock & IPED_ENABLE_MASK);
266 cmpa_buffer.IPED3_END = config->end;
267 break;
268 default:
269 return kStatus_InvalidArgument;
270 }
271 /* Write new CMPA page into FFR */
272 status = FFR_CustFactoryPageWrite(&flash_config, (uint8_t *)&cmpa_buffer, false /* do not seal PFR memory */);
273 }
274
275 /* Lock the IPED IP setting if desired */
276 if (lock == kIPED_RegionLock)
277 {
278 IPED_SetLock(FLEXSPI0, config->option.iped_region);
279 }
280
281 return status;
282 }
283
284 /*!
285 * @brief Configures IPED setting.
286 *
287 * This function is used to re-configure IPED IP based on configuration stored in FFR.
288 * This function also needs to be called after wake up from power-down mode to regenerate IV
289 * encryption key in ELS key store whose presence is necessary for correct IPED operation
290 * during erase and write operations to encrypted regions of internal flash memory
291 * (dependency for correct operation of MEM_Erase() and MEM_Write() after wake up from power-down mode).
292 *
293 * @param coreCtx The pointer to the ROM API driver context structure.
294 * @param config The pointer to the IPED driver configuration structure. If NULL CMPA configuration is used instead.
295 * Note: when providing config structure, you have to call Reconfigure for each IPED region individually starting with
296 * Region 0. Region 0 must be enabled as a base region.
297 *
298 * @retval #kStatus_Success
299 * @retval #kStatus_Fail
300 */
IPED_Reconfigure(api_core_context_t * coreCtx,flexspi_iped_region_arg_t * config)301 status_t IPED_Reconfigure(api_core_context_t *coreCtx, flexspi_iped_region_arg_t *config)
302 {
303 status_t status = kStatus_Fail;
304 uint32_t IvReg[4] = {0};
305 uint32_t ivEraseCounter[4];
306 uint32_t ipedConfig[8];
307 uint32_t ipedStart[4];
308 uint32_t ipedEnd[4];
309 uint8_t lockEnable[4];
310 uint32_t uuid[4];
311 flash_config_t flash_config;
312
313 /* Enable ELS and check keys */
314 status = IPED_ELS_enable();
315 if (kStatus_Success != status)
316 {
317 return kStatus_Fail;
318 }
319
320 /* Clean up Flash driver structure and Init*/
321 memset(&flash_config, 0, sizeof(flash_config_t));
322 if (FLASH_Init(&flash_config) != kStatus_Success)
323 {
324 return kStatus_Fail;
325 }
326
327 /* FFR Init */
328 if (FFR_Init(&flash_config) != kStatus_Success)
329 {
330 return kStatus_Fail;
331 }
332
333 /* Get UUID from FFR */
334 status = FFR_GetUUID(&flash_config, (uint8_t *)uuid);
335 if (kStatus_Success != status)
336 {
337 return kStatus_Fail;
338 }
339
340 /* Check version of CFPA scratch first */
341 uint32_t cfpaScratchVer = 0u;
342 memcpy(&cfpaScratchVer, (void *)(CFPA_SCRATCH_VER), sizeof(uint32_t));
343
344 /* Get CFPA version using FFR ROM API */
345 uint32_t cfpaVer = 0u;
346 if (kStatus_Success !=
347 FFR_GetCustomerInfieldData(&flash_config, (uint8_t *)&cfpaVer, CFPA_VER_OFFSET, sizeof(uint32_t)))
348 {
349 status = kStatus_Fail;
350 return status;
351 }
352
353 /* Compare the version of CFPA scratch and version of CFPA returned by ROM API */
354 if (cfpaScratchVer > cfpaVer)
355 {
356 /* Get IPED_IV_CTRs from CFPA scratch */
357 memcpy(&ivEraseCounter, (void *)CFPA_SCRATCH_IV, sizeof(uint32_t) * IPED_REGION_COUNT);
358 }
359 else
360 {
361 /* Get IPED_IV_CTRs IVs from CFPA ping/pong page */
362 status = FFR_GetCustomerInfieldData(&flash_config, (uint8_t *)ivEraseCounter, CFPA_IPED_IV_OFFSET,
363 sizeof(uint32_t) * IPED_REGION_COUNT);
364 if (kStatus_Success != status)
365 {
366 return kStatus_Fail;
367 }
368 }
369
370 if (config == NULL) /* Read configuration from CMPA */
371 {
372 /* Get IPED start address, end address and lock setting from FFR CMPA */
373 status = FFR_GetCustomerData(
374 &flash_config, (uint8_t *)ipedConfig, CMPA_IPED_START_OFFSET,
375 sizeof(uint32_t) * IPED_REGION_COUNT * 2u); // multiply by 2 because we are reading end and start address
376 if (kStatus_Success != status)
377 {
378 return kStatus_Fail;
379 }
380
381 /* Prepare Lock and Enable values from FFR configuration into array */
382 lockEnable[0] = (ipedConfig[0] & IPED_START_ADDR_LOCK_EN_MASK);
383 lockEnable[1] = (ipedConfig[2] & IPED_START_ADDR_LOCK_EN_MASK);
384 lockEnable[2] = (ipedConfig[4] & IPED_START_ADDR_LOCK_EN_MASK);
385 lockEnable[3] = (ipedConfig[5] & IPED_START_ADDR_LOCK_EN_MASK);
386 /* Prepare Start address values from FFR configuration into array */
387 ipedStart[0] = (ipedConfig[0] & IPED_START_ADDR_MASK);
388 ipedStart[1] = (ipedConfig[2] & IPED_START_ADDR_MASK);
389 ipedStart[2] = (ipedConfig[4] & IPED_START_ADDR_MASK);
390 ipedStart[3] = (ipedConfig[6] & IPED_START_ADDR_MASK);
391 /* Prepare End address values from FFR configuration into array */
392 ipedEnd[0] = (ipedConfig[1] & IPED_END_ADDR_MASK);
393 ipedEnd[1] = (ipedConfig[3] & IPED_END_ADDR_MASK);
394 ipedEnd[2] = (ipedConfig[5] & IPED_END_ADDR_MASK);
395 ipedEnd[3] = (ipedConfig[7] & IPED_END_ADDR_MASK);
396
397 /* Always use 12 rounds */
398 IPED_SetPrinceRounds(FLEXSPI0, kIPED_PrinceRounds12);
399
400 /* Iterate for all internal IPED regions */
401 for (iped_region_t region = kIPED_Region0; region <= kIPED_Region3; region++)
402 {
403 iped_region_t region = kIPED_Region0;
404 /* If not enabled, skip to other region */
405 if (lockEnable[region] == 0u)
406 {
407 continue;
408 }
409
410 /* Write start & end addresses to IPED registers */
411 status = IPED_SetRegionAddressRange(FLEXSPI0, (iped_region_t)region, ipedStart[region], ipedEnd[region]);
412 if (status != kStatus_Success)
413 {
414 break;
415 }
416
417 /* Prepare ivSeed for current region */
418 IvReg[0] = uuid[0];
419 IvReg[1] = uuid[1];
420 IvReg[2] = uuid[2] ^ region;
421 IvReg[3] = ivEraseCounter[region];
422
423 /* Calculate IV as IvReg = AES_ECB_ENC(DUK_derived_key, {ctx_erase_counter, ctx_id}) */
424 status = IPED_ELS_calculate_iv(IvReg);
425 if (status != kStatus_Success)
426 {
427 return kStatus_Fail;
428 }
429
430 /* Load IV into IPED registers */
431 status = IPED_SetRegionIV(FLEXSPI0, (iped_region_t)region, (uint8_t *)IvReg);
432 if (status != kStatus_Success)
433 {
434 return kStatus_Fail;
435 }
436
437 /* Lock region if required */
438 if ((lockEnable[region] == 0x2u) || (lockEnable[region] == 0x3u))
439 {
440 IPED_SetLock(FLEXSPI0, region);
441 }
442 }
443 }
444 else /* Use provided config structure */
445 {
446 /* Write start & end addresses to IPED registers */
447 status =
448 IPED_SetRegionAddressRange(FLEXSPI0, (iped_region_t)config->option.iped_region, config->start, config->end);
449
450 /* Prepare ivSeed for current region */
451 IvReg[0] = uuid[0];
452 IvReg[1] = uuid[1];
453 IvReg[2] = uuid[2] ^ (iped_region_t)config->option.iped_region;
454 IvReg[3] = ivEraseCounter[(iped_region_t)config->option.iped_region];
455
456 /* Calculate IV as IvReg = AES_ECB_ENC(DUK_derived_key, {ctx_erase_counter, ctx_id}) */
457 status = IPED_ELS_calculate_iv(IvReg);
458 if (status != kStatus_Success)
459 {
460 return kStatus_Fail;
461 }
462
463 /* Load IV into IPED registers */
464 status = IPED_SetRegionIV(FLEXSPI0, (iped_region_t)config->option.iped_region, (uint8_t *)IvReg);
465 if (status != kStatus_Success)
466 {
467 return kStatus_Fail;
468 }
469 }
470
471 /* Check if error occured during IPED configuration */
472 if (status != kStatus_Success)
473 {
474 return kStatus_Fail;
475 }
476
477 return status;
478 }
479
IPED_ELS_check_key(uint8_t keyIdx,mcuxClEls_KeyProp_t * pKeyProp)480 static status_t IPED_ELS_check_key(uint8_t keyIdx, mcuxClEls_KeyProp_t *pKeyProp)
481 {
482 /* Check if ELS required keys are available in ELS keystore */
483 MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token,
484 mcuxClEls_GetKeyProperties(keyIdx, pKeyProp)); // Get key propertis from the ELS.
485 // mcuxClEls_GetKeyProperties is a flow-protected function: Check the protection token and the return value
486 if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_GetKeyProperties) != token) || (MCUXCLELS_STATUS_OK != result))
487 return kStatus_Fail;
488 MCUX_CSSL_FP_FUNCTION_CALL_END();
489
490 return kStatus_Success;
491 }
492
IPED_ELS_gen_iv_key(void)493 static status_t IPED_ELS_gen_iv_key(void)
494 {
495 /* The NXP_DIE_MEM_IV_ENC_SK is not loaded and needs to be regenerated (power-down wakeup) */
496 /* Set KDF mask and key properties for NXP_DIE_MEM_IV_ENC_SK */
497 SYSCON->ELS_KDF_MASK = SYSCON_ELS_KDF_MASK;
498 static const uint32_t ddata2[3] = {0x62032504, 0x72f04280, 0x87a2bbae};
499 mcuxClEls_KeyProp_t keyProp;
500 /* Set key properties in structure */
501 keyProp.word.value = MCUXCLELS_KEYPROPERTY_VALUE_AES | MCUXCLELS_KEYPROPERTY_VALUE_GENERAL_PURPOSE_SLOT |
502 MCUXCLELS_KEYPROPERTY_VALUE_ACTIVE;
503 status_t status = kStatus_Fail;
504
505 /* Generate the key using CKDF */
506 MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(
507 result, token,
508 mcuxClEls_Ckdf_Sp800108_Async((mcuxClEls_KeyIndex_t)0, (mcuxClEls_KeyIndex_t)NXP_DIE_MEM_IV_ENC_SK, keyProp,
509 (uint8_t const *)ddata2));
510 if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Ckdf_Sp800108_Async) != token) && (MCUXCLELS_STATUS_OK != result))
511 {
512 return kStatus_Fail;
513 }
514 MCUX_CSSL_FP_FUNCTION_CALL_END();
515
516 /* Wait for CKDF to finish */
517 MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClEls_WaitForOperation(MCUXCLELS_ERROR_FLAGS_CLEAR));
518 if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_WaitForOperation) == token) && (MCUXCLELS_STATUS_OK == result))
519 {
520 status = kStatus_Success;
521 }
522 MCUX_CSSL_FP_FUNCTION_CALL_END();
523
524 return status;
525 }
526
IPED_ELS_enable(void)527 static status_t IPED_ELS_enable(void)
528 {
529 mcuxClEls_KeyProp_t key_properties;
530 status_t status = kStatus_Fail;
531
532 /* Enable ELS and related clocks */
533 status = ELS_PowerDownWakeupInit(ELS);
534 if (status != kStatus_Success)
535 {
536 return kStatus_Fail;
537 }
538
539 /* Check if MEM_ENC_SK key is available in ELS keystore */
540 status = IPED_ELS_check_key(NXP_DIE_EXT_MEM_ENC_SK, &key_properties);
541 if (status != kStatus_Success || key_properties.bits.kactv != 1u)
542 {
543 return kStatus_Fail;
544 }
545
546 /* Check if MEM_IV_ENC_SK key is available in ELS keystore */
547 status = IPED_ELS_check_key(NXP_DIE_MEM_IV_ENC_SK, &key_properties);
548 if (status != kStatus_Success || key_properties.bits.kactv != 1u)
549 {
550 return IPED_ELS_gen_iv_key();
551 }
552
553 return kStatus_Success;
554 }
555
IPED_ELS_calculate_iv(uint32_t * IvReg)556 static status_t IPED_ELS_calculate_iv(uint32_t *IvReg)
557 {
558 mcuxClEls_CipherOption_t cipherOptions = {0};
559 status_t status = kStatus_Fail;
560
561 /* Configure ELS for AES ECB-128, using NXP_DIE_MEM_IV_ENC_SK key */
562 cipherOptions.bits.cphmde = MCUXCLELS_CIPHERPARAM_ALGORITHM_AES_ECB;
563 cipherOptions.bits.dcrpt = MCUXCLELS_CIPHER_ENCRYPT;
564 cipherOptions.bits.extkey = MCUXCLELS_CIPHER_INTERNAL_KEY;
565
566 do
567 {
568 /* Calculate IV as IvReg = AES_ECB_ENC(NXP_DIE_MEM_IV_ENC_SK, ivSeed[127:0]) */
569 /* ivSeed[127:0] = {UUID[96:0] ^ regionNumber[1:0], ivEraseCounter[31:0]} */
570 MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(
571 result, token,
572 mcuxClEls_Cipher_Async(cipherOptions, (mcuxClEls_KeyIndex_t)NXP_DIE_MEM_IV_ENC_SK, NULL,
573 MCUXCLELS_CIPHER_KEY_SIZE_AES_128, (uint8_t *)IvReg, MCUXCLELS_CIPHER_BLOCK_SIZE_AES,
574 NULL, (uint8_t *)IvReg));
575 if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_Cipher_Async) != token) || (MCUXCLELS_STATUS_OK_WAIT != result))
576 break;
577 MCUX_CSSL_FP_FUNCTION_CALL_END();
578
579 MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(
580 result, token,
581 mcuxClEls_WaitForOperation(
582 MCUXCLELS_ERROR_FLAGS_CLEAR)); // Wait for the mcuxClEls_Enable_Async operation to complete.
583 // mcuxClEls_WaitForOperation is a flow-protected function: Check the protection token and the return value
584 if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClEls_WaitForOperation) == token) && (MCUXCLELS_STATUS_OK == result))
585 {
586 status = kStatus_Success;
587 }
588 MCUX_CSSL_FP_FUNCTION_CALL_END();
589 } while (0);
590
591 return status;
592 }
593