1 /*
2  * Copyright 2018 - 2021 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_prince.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 /* Component ID definition, used by tools. */
14 
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.prince"
17 #endif
18 
19 /*******************************************************************************
20  * Variables
21  ******************************************************************************/
22 
23 /*******************************************************************************
24  * Code
25  ******************************************************************************/
26 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
PRINCE_CheckerAlgorithm(uint32_t address,uint32_t length,prince_flags_t flag,flash_config_t * flash_context)27 static secure_bool_t PRINCE_CheckerAlgorithm(uint32_t address,
28                                              uint32_t length,
29                                              prince_flags_t flag,
30                                              flash_config_t *flash_context)
31 {
32     uint32_t temp_base = 0, temp_sr = 0, region_index = 0, contiguous_start_index = 0, contiguous_end_index = 32;
33     secure_bool_t is_prince_region_contiguous      = kSECURE_TRUE;
34     uint8_t prince_iv_code[FLASH_FFR_IV_CODE_SIZE] = {0};
35 
36     if (address >= flash_context->ffrConfig.ffrBlockBase)
37     {
38         /* If it is not in flash region, return true to allow erase/write operation. */
39         return kSECURE_TRUE;
40     }
41 
42     /* Iterate for all PRINCE regions */
43     for (region_index = (uint32_t)kPRINCE_Region0; region_index <= (uint32_t)kPRINCE_Region2; region_index++)
44     {
45         contiguous_start_index = 0;
46         contiguous_end_index   = 32;
47         switch (region_index)
48         {
49             case (uint32_t)kPRINCE_Region0:
50                 temp_base = PRINCE->BASE_ADDR0;
51                 temp_sr   = PRINCE->SR_ENABLE0;
52                 break;
53 
54             case (uint32_t)kPRINCE_Region1:
55                 temp_base = PRINCE->BASE_ADDR1;
56                 temp_sr   = PRINCE->SR_ENABLE1;
57                 break;
58 
59             case (uint32_t)kPRINCE_Region2:
60                 temp_base = PRINCE->BASE_ADDR2;
61                 temp_sr   = PRINCE->SR_ENABLE2;
62                 break;
63 
64             default:
65                 /* All the cases have been listed above, the default clause should not be reached. */
66                 break;
67         }
68 
69         if (((address >= temp_base) &&
70              ((address + length) < (temp_base + (FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 32U * 1024U)))) &&
71             (temp_sr != 0U))
72         {
73             /* Check if the mask is contiguous */
74             secure_bool_t first_set_bit_found  = kSECURE_FALSE;
75             secure_bool_t contiguous_end_found = kSECURE_FALSE;
76             for (uint32_t i = 0; i < 32U; i++)
77             {
78                 if (0U != (temp_sr & (1UL << i)))
79                 {
80                     if (kSECURE_FALSE == first_set_bit_found)
81                     {
82                         first_set_bit_found    = kSECURE_TRUE;
83                         contiguous_start_index = i;
84                     }
85                     if (kSECURE_TRUE == contiguous_end_found)
86                     {
87                         is_prince_region_contiguous = kSECURE_FALSE;
88                         break;
89                     }
90                 }
91                 else
92                 {
93                     if ((kSECURE_TRUE == first_set_bit_found) && (kSECURE_FALSE == contiguous_end_found))
94                     {
95                         contiguous_end_found = kSECURE_TRUE;
96                         contiguous_end_index = i;
97                     }
98                 }
99             }
100         }
101         else
102         {
103             continue; /* No encryption enabled, continue with the next region checking. */
104         }
105 
106         /* Check if the provided memory range covers all addresses defined in the SR mask */
107         if ((kSECURE_TRUE == is_prince_region_contiguous) &&
108             ((address <= (temp_base + (contiguous_start_index * FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 1024U)))) &&
109             (((address + length) >=
110               (temp_base + (contiguous_end_index * FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 1024U)))))
111         {
112             /* In case of erase operation, invalidate the old PRINCE IV by regenerating the new one */
113             if (kPRINCE_Flag_EraseCheck == flag)
114             {
115                 /* Re-generate the PRINCE IV in case of erase operation */
116 
117                 /* Generate new IV code for the PRINCE region and store the new IV into the respective FFRs */
118                 if (kStatus_Success ==
119                     PRINCE_GenNewIV((prince_region_t)region_index, &prince_iv_code[0], true, flash_context))
120                 {
121                     /* Store the new IV for the PRINCE region into PRINCE registers. */
122                     if (kStatus_Success == PRINCE_LoadIV((prince_region_t)region_index, &prince_iv_code[0]))
123                     {
124                         /* Encryption is enabled, all subregions are to be erased/written at once, IV successfully
125                          * regenerated, return true to allow erase operation. */
126                         return kSECURE_TRUE;
127                     }
128                 }
129                 /* Encryption is enabled, all subregions are to be erased/written at once but IV has not been correctly
130                  * regenerated, return false to disable erase operation. */
131                 return kSECURE_FALSE;
132             }
133 
134             /* Encryption is enabled and all subregions are to be erased/written at once, return true to allow
135              * erase/write operation. */
136             return kSECURE_TRUE;
137         }
138         /* The provided memory range does not cover all addresses defined in the SR mask. */
139         else
140         {
141             /* Is the provided memory range outside the addresses defined by the SR mask? */
142             if ((kSECURE_TRUE == is_prince_region_contiguous) &&
143                 ((((address + length) <=
144                    (temp_base + (contiguous_start_index * FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 1024U)))) ||
145                  ((address >= (temp_base + (contiguous_end_index * FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 1024U))))))
146             {
147                 /* No encryption enabled for the provided memory range, true could be returned to allow erase/write
148                    operation, but due to the same base address for all three prince regions on Niobe4Mini we should
149                    continue with other regions (SR mask) checking. */
150                 continue;
151             }
152             else
153             {
154                 /* Encryption is enabled but not all subregions are to be erased/written at once, return false to
155                  * disable erase/write operation. */
156                 return kSECURE_FALSE;
157             }
158         }
159     }
160     return kSECURE_TRUE;
161 }
162 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
163 
164 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
165 /*!
166  * @brief Generate new IV code.
167  *
168  * This function generates new IV code and stores it into the persistent memory.
169  * Ensure about 800 bytes free space on the stack when calling this routine with the store parameter set to true!
170  *
171  * @param region PRINCE region index.
172  * @param iv_code IV code pointer used for storing the newly generated 52 bytes long IV code.
173  * @param store flag to allow storing the newly generated IV code into the persistent memory (FFR).
174  * @param flash_context pointer to the flash driver context structure.
175  *
176  * @return kStatus_Success upon success
177  * @return kStatus_Fail    otherwise, kStatus_Fail is also returned if the key code for the particular
178  *                         PRINCE region is not present in the keystore (though new IV code has been provided)
179  */
PRINCE_GenNewIV(prince_region_t region,uint8_t * iv_code,bool store,flash_config_t * flash_context)180 status_t PRINCE_GenNewIV(prince_region_t region, uint8_t *iv_code, bool store, flash_config_t *flash_context)
181 {
182     status_t status                                = kStatus_Fail;
183     uint8_t prince_iv_code[FLASH_FFR_IV_CODE_SIZE] = {0};
184     uint8_t tempBuffer[FLASH_FFR_MAX_PAGE_SIZE]    = {0};
185 
186     /* Make sure PUF is started to allow key and IV code decryption and generation */
187     if (true != PUF_IsGetKeyAllowed(PUF))
188     {
189         return status;
190     }
191 
192     /* Generate new IV code for the PRINCE region */
193     status =
194         PUF_SetIntrinsicKey(PUF, (puf_key_index_register_t)(uint32_t)((uint32_t)kPUF_KeyIndex_02 + (uint32_t)region), 8,
195                             &prince_iv_code[0], FLASH_FFR_IV_CODE_SIZE);
196     if ((kStatus_Success == status) && (true == store))
197     {
198         /* Store the new IV code for the PRINCE region into the respective FFRs. */
199         /* Create a new version of "Customer Field Programmable" (CFP) page. */
200         if ((int32_t)kStatus_FLASH_Success ==
201             FFR_GetCustomerInfieldData(flash_context, (uint8_t *)tempBuffer, 0, FLASH_FFR_MAX_PAGE_SIZE))
202         {
203             /* Set the IV code in the page */
204             (void)memcpy(&tempBuffer[offsetof(cfpa_cfg_info_t, ivCodePrinceRegion) +
205                                      (((uint32_t)region * sizeof(cfpa_cfg_iv_code_t))) + 4U],
206                          &prince_iv_code[0], FLASH_FFR_IV_CODE_SIZE);
207 
208             uint32_t *p32    = (uint32_t *)(uint32_t)tempBuffer;
209             uint32_t version = p32[1];
210             if (version == 0xFFFFFFFFu)
211             {
212                 return kStatus_Fail;
213             }
214             version++;
215             p32[1] = version;
216 
217             /* Program the page and enable firewall for "Customer field area" */
218             if ((int32_t)kStatus_FLASH_Success ==
219                 FFR_InfieldPageWrite(flash_context, (uint8_t *)tempBuffer, FLASH_FFR_MAX_PAGE_SIZE))
220             {
221                 status = kStatus_Success;
222             }
223             else
224             {
225                 status = kStatus_Fail;
226             }
227         }
228     }
229     if (status == kStatus_Success)
230     {
231         /* Pass the new IV code */
232         (void)memcpy(iv_code, &prince_iv_code[0], FLASH_FFR_IV_CODE_SIZE);
233     }
234 
235     return status;
236 }
237 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
238 
239 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
240 /*!
241  * @brief Load IV code.
242  *
243  * This function enables IV code loading into the PRINCE bus encryption engine.
244  *
245  * @param region PRINCE region index.
246  * @param iv_code IV code pointer used for passing the IV code.
247  *
248  * @return kStatus_Success upon success
249  * @return kStatus_Fail    otherwise
250  */
PRINCE_LoadIV(prince_region_t region,uint8_t * iv_code)251 status_t PRINCE_LoadIV(prince_region_t region, uint8_t *iv_code)
252 {
253     status_t status      = kStatus_Fail;
254     uint32_t keyIndex    = (0x0Fu & (uint32_t)iv_code[1]);
255     uint8_t prince_iv[8] = {0};
256 
257     /* Make sure PUF is started to allow key and IV code decryption and generation */
258     if (true != PUF_IsGetKeyAllowed(PUF))
259     {
260         return kStatus_Fail;
261     }
262 
263     /* Check if region number matches the PUF index value */
264     if (((uint32_t)kPUF_KeyIndex_02 + (uint32_t)region) == (uint32_t)keyIndex)
265     {
266         /* Decrypt the IV */
267         if (kStatus_Success == PUF_GetKey(PUF, iv_code, FLASH_FFR_IV_CODE_SIZE, &prince_iv[0], 8))
268         {
269             /* Store the new IV for the PRINCE region into PRINCE registers. */
270             (void)PRINCE_SetRegionIV(PRINCE, (prince_region_t)region, prince_iv);
271             status = kStatus_Success;
272         }
273     }
274 
275     return status;
276 }
277 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
278 
279 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
280 /*!
281  * @brief Allow encryption/decryption for specified address range.
282  *
283  * This function sets the encryption/decryption for specified address range.
284  * The SR mask value for the selected Prince region is calculated from provided
285  * start_address and length parameters. This calculated value is OR'ed with the
286  * actual SR mask value and stored into the PRINCE SR_ENABLE register and also
287  * into the persistent memory (FFR) to be used after the device reset. It is
288  * possible to define several nonadjacent encrypted areas within one Prince
289  * region when calling this function repeatedly. If the length parameter is set
290  * to 0, the SR mask value is set to 0 and thus the encryption/decryption for
291  * the whole selected Prince region is disabled.
292  * Ensure about 800 bytes free space on the stack when calling this routine!
293  *
294  * @param region PRINCE region index.
295  * @param start_address start address of the area to be encrypted/decrypted.
296  * @param length length of the area to be encrypted/decrypted.
297  * @param flash_context pointer to the flash driver context structure.
298  * @param regenerate_iv flag to allow IV code regenerating, storing into
299  *        the persistent memory (FFR) and loading into the PRINCE engine
300  *
301  * @return kStatus_Success upon success
302  * @return kStatus_Fail    otherwise
303  */
PRINCE_SetEncryptForAddressRange(prince_region_t region,uint32_t start_address,uint32_t length,flash_config_t * flash_context,bool regenerate_iv)304 status_t PRINCE_SetEncryptForAddressRange(
305     prince_region_t region, uint32_t start_address, uint32_t length, flash_config_t *flash_context, bool regenerate_iv)
306 {
307     status_t status           = kStatus_Fail;
308     uint32_t srEnableRegister = 0;
309     uint32_t alignedStartAddress;
310     uint32_t prince_base_addr_ffr_word          = 0;
311     uint32_t end_address                        = start_address + length;
312     uint32_t prince_region_base_address         = 0;
313     uint8_t tempBuffer[FLASH_FFR_MAX_PAGE_SIZE] = {0};
314 
315     /* Check input parameters. */
316     if (NULL == flash_context)
317     {
318         return kStatus_Fail;
319     }
320 
321     /* Check the address range, region borders crossing. */
322 #if (defined(FSL_PRINCE_DRIVER_LPC55S0x)) || (defined(FSL_PRINCE_DRIVER_LPC55S1x)) || \
323     (defined(FSL_PRINCE_DRIVER_LPC55S2x)) || (defined(FSL_PRINCE_DRIVER_LPC55S3x))
324     if ((start_address > FSL_PRINCE_DRIVER_MAX_FLASH_ADDR) ||
325         ((start_address < FSL_PRINCE_DRIVER_MAX_FLASH_ADDR) && (end_address > FSL_PRINCE_DRIVER_MAX_FLASH_ADDR)))
326     {
327         return kStatus_Fail;
328     }
329 #endif
330 #if (defined(FSL_PRINCE_DRIVER_LPC55S6x))
331     if ((start_address > FSL_PRINCE_DRIVER_MAX_FLASH_ADDR) ||
332         ((start_address < 0x40000U) && (end_address > 0x40000U)) ||
333         ((start_address < 0x80000U) && (end_address > 0x80000U)) ||
334         ((start_address < FSL_PRINCE_DRIVER_MAX_FLASH_ADDR) && (end_address > FSL_PRINCE_DRIVER_MAX_FLASH_ADDR)))
335     {
336         return kStatus_Fail;
337     }
338 #endif
339 
340     if (true == regenerate_iv)
341     {
342         uint8_t prince_iv_code[FLASH_FFR_IV_CODE_SIZE] = {0};
343 
344         /* Generate new IV code for the PRINCE region and store the new IV into the respective FFRs */
345         status = PRINCE_GenNewIV((prince_region_t)region, &prince_iv_code[0], true, flash_context);
346         if (kStatus_Success != status)
347         {
348             return kStatus_Fail;
349         }
350 
351         /* Store the new IV for the PRINCE region into PRINCE registers. */
352         status = PRINCE_LoadIV((prince_region_t)region, &prince_iv_code[0]);
353         if (kStatus_Success != status)
354         {
355             return kStatus_Fail;
356         }
357     }
358 
359     alignedStartAddress = ALIGN_DOWN(start_address, (int32_t)FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 1024);
360 
361     uint32_t subregion = alignedStartAddress / (FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 1024U);
362     if (subregion < (32U))
363     {
364         /* PRINCE_Region0 */
365         prince_region_base_address = 0;
366     }
367     else if (subregion < (64U))
368     {
369         /* PRINCE_Region1 */
370         subregion                  = subregion - 32U;
371         prince_region_base_address = 0x40000;
372     }
373     else
374     {
375         /* PRINCE_Region2 */
376         subregion                  = subregion - 64U;
377         prince_region_base_address = 0x80000;
378     }
379 
380     /* If length > 0 then srEnableRegister mask is set based on the alignedStartAddress and the length.
381        If the length is 0, srEnableRegister should be kept 0 (no subregion enabled). */
382     if (length != 0U)
383     {
384         srEnableRegister = (1UL << subregion);
385         alignedStartAddress += (FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 1024U);
386 
387         while (alignedStartAddress < (start_address + length))
388         {
389             subregion++;
390             srEnableRegister |= (1UL << subregion);
391             alignedStartAddress += (FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 1024U);
392         }
393 
394         uint32_t srEnableRegisterActual = 0;
395         (void)PRINCE_GetRegionSREnable(PRINCE, (prince_region_t)region, &srEnableRegisterActual);
396         srEnableRegister |= srEnableRegisterActual;
397     }
398 
399     /* Store BASE_ADDR into PRINCE register before storing the SR to avoid en/decryption triggering
400        from addresses being defined by current BASE_ADDR register content (could be 0 and the decryption
401        of actually executed code can be started causing the hardfault then). */
402     status = PRINCE_SetRegionBaseAddress(PRINCE, (prince_region_t)region, prince_region_base_address);
403     if (kStatus_Success != status)
404     {
405         return status;
406     }
407 
408     /* Store SR into PRINCE register */
409     status = PRINCE_SetRegionSREnable(PRINCE, (prince_region_t)region, srEnableRegister);
410     if (kStatus_Success != status)
411     {
412         return status;
413     }
414 
415     /* Store SR and BASE_ADDR into CMPA FFR */
416     if (kStatus_Success == FFR_GetCustomerData(flash_context, (uint8_t *)&tempBuffer, 0, FLASH_FFR_MAX_PAGE_SIZE))
417     {
418         /* Set the PRINCE_SR_X in the page */
419         (void)memcpy((uint32_t *)(uintptr_t)&tempBuffer[offsetof(cmpa_cfg_info_t, princeSr) +
420                                                         ((uint32_t)region * sizeof(uint32_t))],
421                      &srEnableRegister, sizeof(uint32_t));
422         /* Set the ADDRX_PRG in the page */
423         (void)memcpy(&prince_base_addr_ffr_word,
424                      (const uint32_t *)(uintptr_t)&tempBuffer[offsetof(cmpa_cfg_info_t, princeBaseAddr)],
425                      sizeof(uint32_t));
426         prince_base_addr_ffr_word &=
427             ~(((uint32_t)FLASH_CMPA_PRINCE_BASE_ADDR_ADDR0_PRG_MASK) << ((uint32_t)region * 4U));
428         prince_base_addr_ffr_word |= (((prince_region_base_address >> PRINCE_BASE_ADDR0_ADDR_PRG_SHIFT) &
429                                        FLASH_CMPA_PRINCE_BASE_ADDR_ADDR0_PRG_MASK)
430                                       << ((uint32_t)region * 4U));
431         (void)memcpy((uint32_t *)(uintptr_t)&tempBuffer[offsetof(cmpa_cfg_info_t, princeBaseAddr)],
432                      &prince_base_addr_ffr_word, sizeof(uint32_t));
433 
434         /* Program the CMPA page, set seal_part parameter to false (used during development to avoid sealing the
435          * part)
436          */
437         status = FFR_CustFactoryPageWrite(flash_context, (uint8_t *)tempBuffer, false);
438     }
439 
440     return status;
441 }
442 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
443 
444 /*!
445  * @brief Gets the PRINCE Sub-Region Enable register.
446  *
447  * This function gets PRINCE SR_ENABLE register.
448  *
449  * @param base PRINCE peripheral address.
450  * @param region PRINCE region index.
451  * @param sr_enable Sub-Region Enable register pointer.
452  *
453  * @return kStatus_Success upon success
454  * @return kStatus_InvalidArgument
455  */
PRINCE_GetRegionSREnable(PRINCE_Type * base,prince_region_t region,uint32_t * sr_enable)456 status_t PRINCE_GetRegionSREnable(PRINCE_Type *base, prince_region_t region, uint32_t *sr_enable)
457 {
458     status_t status = kStatus_Success;
459 
460     switch (region)
461     {
462         case kPRINCE_Region0:
463             *sr_enable = base->SR_ENABLE0;
464             break;
465 
466         case kPRINCE_Region1:
467             *sr_enable = base->SR_ENABLE1;
468             break;
469 
470         case kPRINCE_Region2:
471             *sr_enable = base->SR_ENABLE2;
472             break;
473 
474         default:
475             status = kStatus_InvalidArgument;
476             break;
477     }
478 
479     return status;
480 }
481 
482 /*!
483  * @brief Gets the PRINCE region base address register.
484  *
485  * This function gets PRINCE BASE_ADDR register.
486  *
487  * @param base PRINCE peripheral address.
488  * @param region PRINCE region index.
489  * @param region_base_addr Region base address pointer.
490  *
491  * @return kStatus_Success upon success
492  * @return kStatus_InvalidArgument
493  */
PRINCE_GetRegionBaseAddress(PRINCE_Type * base,prince_region_t region,uint32_t * region_base_addr)494 status_t PRINCE_GetRegionBaseAddress(PRINCE_Type *base, prince_region_t region, uint32_t *region_base_addr)
495 {
496     status_t status = kStatus_Success;
497 
498     switch (region)
499     {
500         case kPRINCE_Region0:
501             *region_base_addr = base->BASE_ADDR0;
502             break;
503 
504         case kPRINCE_Region1:
505             *region_base_addr = base->BASE_ADDR1;
506             break;
507 
508         case kPRINCE_Region2:
509             *region_base_addr = base->BASE_ADDR2;
510             break;
511 
512         default:
513             status = kStatus_InvalidArgument;
514             break;
515     }
516 
517     return status;
518 }
519 
520 /*!
521  * @brief Sets the PRINCE region IV.
522  *
523  * This function sets specified AES IV for the given region.
524  *
525  * @param base PRINCE peripheral address.
526  * @param region Selection of the PRINCE region to be configured.
527  * @param iv 64-bit AES IV in little-endian byte order.
528  *
529  * @return kStatus_Success upon success
530  * @return kStatus_InvalidArgument
531  */
PRINCE_SetRegionIV(PRINCE_Type * base,prince_region_t region,const uint8_t iv[8])532 status_t PRINCE_SetRegionIV(PRINCE_Type *base, prince_region_t region, const uint8_t iv[8])
533 {
534     status_t status              = kStatus_Fail;
535     volatile uint32_t *IVMsb_reg = NULL;
536     volatile uint32_t *IVLsb_reg = NULL;
537 
538     switch (region)
539     {
540         case kPRINCE_Region0:
541             IVLsb_reg = &base->IV_LSB0;
542             IVMsb_reg = &base->IV_MSB0;
543             break;
544 
545         case kPRINCE_Region1:
546             IVLsb_reg = &base->IV_LSB1;
547             IVMsb_reg = &base->IV_MSB1;
548             break;
549 
550         case kPRINCE_Region2:
551             IVLsb_reg = &base->IV_LSB2;
552             IVMsb_reg = &base->IV_MSB2;
553             break;
554 
555         default:
556             status = kStatus_InvalidArgument;
557             break;
558     }
559 
560     if (status != kStatus_InvalidArgument)
561     {
562         *IVLsb_reg = ((uint32_t *)(uintptr_t)iv)[0];
563         *IVMsb_reg = ((uint32_t *)(uintptr_t)iv)[1];
564         status     = kStatus_Success;
565     }
566 
567     return status;
568 }
569 
570 /*!
571  * @brief Sets the PRINCE region base address.
572  *
573  * This function configures PRINCE region base address.
574  *
575  * @param base PRINCE peripheral address.
576  * @param region Selection of the PRINCE region to be configured.
577  * @param region_base_addr Base Address for region.
578  *
579  * @return kStatus_Success upon success
580  * @return kStatus_InvalidArgument
581  */
PRINCE_SetRegionBaseAddress(PRINCE_Type * base,prince_region_t region,uint32_t region_base_addr)582 status_t PRINCE_SetRegionBaseAddress(PRINCE_Type *base, prince_region_t region, uint32_t region_base_addr)
583 {
584     status_t status = kStatus_Success;
585 
586     /* Check input parameters. */
587 #if (defined(FSL_PRINCE_DRIVER_LPC55S0x)) || (defined(FSL_PRINCE_DRIVER_LPC55S1x)) || \
588     (defined(FSL_PRINCE_DRIVER_LPC55S2x)) || (defined(FSL_PRINCE_DRIVER_LPC55S3x))
589     if (region_base_addr > 0U)
590     {
591         return kStatus_InvalidArgument;
592     }
593 #endif
594 #if (defined(FSL_PRINCE_DRIVER_LPC55S6x))
595     if (region_base_addr > 0x80000U)
596     {
597         return kStatus_InvalidArgument;
598     }
599 #endif
600 
601     switch (region)
602     {
603         case kPRINCE_Region0:
604             base->BASE_ADDR0 = region_base_addr;
605             break;
606 
607         case kPRINCE_Region1:
608             base->BASE_ADDR1 = region_base_addr;
609             break;
610 
611         case kPRINCE_Region2:
612             base->BASE_ADDR2 = region_base_addr;
613             break;
614 
615         default:
616             status = kStatus_InvalidArgument;
617             break;
618     }
619 
620     return status;
621 }
622 
623 /*!
624  * @brief Sets the PRINCE Sub-Region Enable register.
625  *
626  * This function configures PRINCE SR_ENABLE register.
627  *
628  * @param base PRINCE peripheral address.
629  * @param region Selection of the PRINCE region to be configured.
630  * @param sr_enable Sub-Region Enable register value.
631  *
632  * @return kStatus_Success upon success
633  * @return kStatus_InvalidArgument
634  */
PRINCE_SetRegionSREnable(PRINCE_Type * base,prince_region_t region,uint32_t sr_enable)635 status_t PRINCE_SetRegionSREnable(PRINCE_Type *base, prince_region_t region, uint32_t sr_enable)
636 {
637     status_t status = kStatus_Success;
638 
639     switch (region)
640     {
641         case kPRINCE_Region0:
642             base->SR_ENABLE0 = sr_enable;
643             break;
644 
645         case kPRINCE_Region1:
646             base->SR_ENABLE1 = sr_enable;
647             break;
648 
649         case kPRINCE_Region2:
650             base->SR_ENABLE2 = sr_enable;
651             break;
652 
653         default:
654             status = kStatus_InvalidArgument;
655             break;
656     }
657 
658     return status;
659 }
660 
661 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
662 /*!
663  * @brief Erases the flash sectors encompassed by parameters passed into function.
664  *
665  * This function erases the appropriate number of flash sectors based on the
666  * desired start address and length. It deals with the flash erase function
667  * complenentary to the standard erase API of the IAP1 driver. This implementation
668  * additionally checks if the whole encrypted PRINCE subregions are erased at once
669  * to avoid secrets revealing. The checker implementation is limited to one contiguous
670  * PRINCE-controlled memory area.
671  *
672  * @param config The pointer to the flash driver context structure.
673  * @param start The start address of the desired flash memory to be erased.
674  *              The start address needs to be prince-sburegion-aligned.
675  * @param lengthInBytes The length, given in bytes (not words or long-words)
676  *                      to be erased. Must be prince-sburegion-size-aligned.
677  * @param key The value used to validate all flash erase APIs.
678  *
679  * @return #kStatus_FLASH_Success API was executed successfully.
680  * @return #kStatus_FLASH_InvalidArgument An invalid argument is provided.
681  * @return #kStatus_FLASH_AlignmentError The parameter is not aligned with the specified baseline.
682  * @return #kStatus_FLASH_AddressError The address is out of range.
683  * @return #kStatus_FLASH_EraseKeyError The API erase key is invalid.
684  * @return #kStatus_FLASH_CommandFailure Run-time error during the command execution.
685  * @return #kStatus_FLASH_CommandNotSupported Flash API is not supported.
686  * @return #kStatus_FLASH_EccError A correctable or uncorrectable error during command execution.
687  * @return #kStatus_FLASH_EncryptedRegionsEraseNotDoneAtOnce Encrypted flash subregions are not erased at once.
688  */
PRINCE_FlashEraseWithChecker(flash_config_t * config,uint32_t start,uint32_t lengthInBytes,uint32_t key)689 status_t PRINCE_FlashEraseWithChecker(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key)
690 {
691     /* Check input parameters. */
692     if (NULL == config)
693     {
694         return kStatus_Fail;
695     }
696     /* Check that the whole encrypted region is erased at once. */
697     if (kSECURE_TRUE != PRINCE_CheckerAlgorithm(start, lengthInBytes, kPRINCE_Flag_EraseCheck, config))
698     {
699         return (int32_t)kStatus_FLASH_EncryptedRegionsEraseNotDoneAtOnce;
700     }
701     return FLASH_Erase(config, start, lengthInBytes, key);
702 }
703 
704 /*!
705  * @brief Programs flash with data at locations passed in through parameters.
706  *
707  * This function programs the flash memory with the desired data for a given
708  * flash area as determined by the start address and the length. It deals with the
709  * flash program function complenentary to the standard program API of the IAP1 driver.
710  * This implementation additionally checks if the whole PRINCE subregions are
711  * programmed at once to avoid secrets revealing. The checker implementation is limited
712  * to one contiguous PRINCE-controlled memory area.
713  *
714  * @param config The pointer to the flash driver context structure.
715  * @param start The start address of the desired flash memory to be programmed. Must be
716  *              prince-sburegion-aligned.
717  * @param src A pointer to the source buffer of data that is to be programmed
718  *            into the flash.
719  * @param lengthInBytes The length, given in bytes (not words or long-words),
720  *                      to be programmed. Must be prince-sburegion-size-aligned.
721  *
722  * @return #kStatus_FLASH_Success API was executed successfully.
723  * @return #kStatus_FLASH_InvalidArgument An invalid argument is provided.
724  * @return #kStatus_FLASH_AlignmentError Parameter is not aligned with the specified baseline.
725  * @return #kStatus_FLASH_AddressError Address is out of range.
726  * @return #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses.
727  * @return #kStatus_FLASH_CommandFailure Run-time error during the command execution.
728  * @return #kStatus_FLASH_CommandFailure Run-time error during the command execution.
729  * @return #kStatus_FLASH_CommandNotSupported Flash API is not supported.
730  * @return #kStatus_FLASH_EccError A correctable or uncorrectable error during command execution.
731  * @return #kStatus_FLASH_SizeError Encrypted flash subregions are not programmed at once.
732  */
PRINCE_FlashProgramWithChecker(flash_config_t * config,uint32_t start,uint8_t * src,uint32_t lengthInBytes)733 status_t PRINCE_FlashProgramWithChecker(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
734 {
735     /* Check input parameters. */
736     if (NULL == config)
737     {
738         return kStatus_Fail;
739     }
740     /* Check that the whole encrypted subregions will be writen at once. */
741     if (kSECURE_TRUE != PRINCE_CheckerAlgorithm(start, lengthInBytes, kPRINCE_Flag_WriteCheck, config))
742     {
743         return (int32_t)kStatus_FLASH_SizeError;
744     }
745     return FLASH_Program(config, start, src, lengthInBytes);
746 }
747 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
748 
749 #if defined(FSL_PRINCE_DRIVER_LPC55S3x)
750 static status_t PRINCE_CSS_generate_random(uint8_t *output, size_t outputByteLen);
751 static status_t PRINCE_CSS_check_key(uint8_t keyIdx, mcuxClCss_KeyProp_t *pKeyProp);
752 static status_t PRINCE_CSS_gen_iv_key(void);
753 static status_t PRINCE_CSS_enable(void);
754 static status_t PRINCE_CSS_calculate_iv(uint32_t *IvReg);
755 
756 /*!
757  * @brief Configures PRINCE setting.
758  *
759  * This function does the initial PRINCE configuration via ROM IAP API call.
760  * PRINCE_SR_x configuration for each region configuration is stored into FFR (CMPA).
761  * PRINCE IV erase counters (MCTR_INT_IV_CTRx) in CFPA are updated accordingly.
762  *
763  * Note: This function is expected to be called once in the device lifetime,
764  * typically during the initial device provisioning, since it is programming the CMPA pages in PFR flash.
765  *
766  * @param coreCtx The pointer to the ROM API driver context structure.
767  * @param config The pointer to the PRINCE driver configuration structure.
768  *
769  * @retval #kStatus_Success
770  * @retval #kStatus_CommandUnsupported
771  * @retval #kStatus_InvalidArgument
772  * @retval #kStatus_FLASH_ModifyProtectedAreaDisallowed
773  * @retval #kStatusMemoryRangeInvalid
774  * @retval #kStatus_Fail
775  * @retval #kStatus_OutOfRange
776  * @retval #kStatus_SPI_BaudrateNotSupport
777  */
PRINCE_Configure(api_core_context_t * coreCtx,prince_prot_region_arg_t * config)778 status_t PRINCE_Configure(api_core_context_t *coreCtx, prince_prot_region_arg_t *config)
779 {
780     /* Enable CSS and check keys */
781     if (kStatus_Success != PRINCE_CSS_enable())
782     {
783         return kStatus_Fail;
784     }
785 
786     return MEM_Config(coreCtx, (uint32_t *)config, kMemoryInternal);
787 }
788 
789 /*!
790  * @brief Configures PRINCE setting.
791  *
792  * This function is used to re-configure PRINCE IP based on configuration stored in FFR.
793  * This function also needs to be called after wake up from power-down mode to regenerate IV
794  * encryption key in CSS key store whose presence is necessary for correct PRINCE operation
795  * during erase and write operations to encrypted regions of internal flash memory
796  * (dependency for correct operation of MEM_Erase() and MEM_Write() after wake up from power-down mode).
797  *
798  * @param coreCtx The pointer to the ROM API driver context structure.
799  *
800  * @retval #kStatus_Success
801  * @retval #kStatus_Fail
802  */
PRINCE_Reconfigure(api_core_context_t * coreCtx)803 status_t PRINCE_Reconfigure(api_core_context_t *coreCtx)
804 {
805     status_t status = kStatus_Fail;
806     uint64_t princeMask;
807     uint32_t IvReg[4] = {0};
808     uint32_t ivEraseCounter[3];
809     uint32_t srEnable[3];
810     uint32_t uuid[4];
811     flash_config_t flash_config;
812     uint32_t lockWord;
813     uint8_t lock[3];
814 
815     /* Enable CSS and check keys */
816     status = PRINCE_CSS_enable();
817     if (kStatus_Success != status)
818     {
819         return kStatus_Fail;
820     }
821 
822     /* Set PRINCE mask value. */
823     status = PRINCE_CSS_generate_random((uint8_t *)&princeMask, sizeof(princeMask));
824     if (kStatus_Success != status)
825     {
826         return kStatus_Fail;
827     }
828     PRINCE_SetMask(PRINCE, princeMask);
829 
830     /* Clean up Flash driver structure and Init*/
831     memset(&flash_config, 0, sizeof(flash_config_t));
832     if (FLASH_Init(&flash_config) != kStatus_Success)
833     {
834         return kStatus_Fail;
835     }
836 
837     /* FFR Init */
838     if (FFR_Init(&flash_config) != kStatus_Success)
839     {
840         return kStatus_Fail;
841     }
842 
843     /* Get UUID from FFR */
844     status = FFR_GetUUID(&flash_config, (uint8_t *)uuid);
845     if (kStatus_Success != status)
846     {
847         return kStatus_Fail;
848     }
849 
850     /* Check version of CFPA scratch first */
851     uint32_t cfpaScratchVer = 0u;
852     memcpy(&cfpaScratchVer, (void *)(CFPA_SCRATCH_VER), sizeof(uint32_t));
853 
854     /* Get CFPA version using FFR ROM API */
855     uint32_t cfpaVer = 0u;
856     if (kStatus_Success !=
857         FFR_GetCustomerInfieldData(&flash_config, (uint8_t *)&cfpaVer, CFPA_VER_OFFSET, sizeof(uint32_t)))
858     {
859         status = kStatus_Fail;
860         return status;
861     }
862 
863     /* Compare the version of CFPA scratch and version of CFPA returned by ROM API */
864     if (cfpaScratchVer > cfpaVer)
865     {
866         /* Get PRINCE_IV_CTRs from CFPA scratch */
867         memcpy(&ivEraseCounter, (void *)CFPA_SCRATCH_IV, sizeof(uint32_t) * PRINCE_REGION_COUNT);
868     }
869     else
870     {
871         /* Get PRINCE_IV_CTRs IVs from CFPA ping/pong page */
872         status = FFR_GetCustomerInfieldData(&flash_config, (uint8_t *)ivEraseCounter, CFPA_PRINCE_IV_OFFSET,
873                                             sizeof(uint32_t) * PRINCE_REGION_COUNT);
874         if (kStatus_Success != status)
875         {
876             return kStatus_Fail;
877         }
878     }
879 
880     /* Get PRINCE sub-region enable word from FFR */
881     status = FFR_GetCustomerData(&flash_config, (uint8_t *)srEnable, CMPA_PRINCE_SR_OFFSET,
882                                  sizeof(uint32_t) * PRINCE_REGION_COUNT);
883     if (kStatus_Success != status)
884     {
885         return kStatus_Fail;
886     }
887 
888     /* Get PRINCE lock setting from FFR */
889     status = FFR_GetCustomerData(&flash_config, (uint8_t *)&lockWord, CMPA_PRINCE_LOCK_OFFSET, sizeof(uint32_t));
890     if (kStatus_Success != status)
891     {
892         return kStatus_Fail;
893     }
894 
895     lock[0] = (lockWord & PRINCE_BASE_ADDR_LOCK_REG0_MASK) >> PRINCE_BASE_ADDR_LOCK_REG0_SHIFT;
896     lock[1] = (lockWord & PRINCE_BASE_ADDR_LOCK_REG1_MASK) >> PRINCE_BASE_ADDR_LOCK_REG1_SHIFT;
897     lock[2] = (lockWord & PRINCE_BASE_ADDR_LOCK_REG2_MASK) >> PRINCE_BASE_ADDR_LOCK_REG2_SHIFT;
898 
899     /* Iterate for all internal PRINCE regions */
900     for (prince_region_t region = kPRINCE_Region0; region <= kPRINCE_Region2; region++)
901     {
902         /* Set region base address. Should be always 0x0 on LPC55S36 */
903         status = PRINCE_SetRegionBaseAddress(PRINCE, (prince_region_t)region, 0x0u);
904         if (kStatus_Success != status)
905         {
906             return kStatus_Fail;
907         }
908 
909         status = PRINCE_SetRegionSREnable(PRINCE, region, srEnable[region]);
910         if (kStatus_Success != status)
911         {
912             return kStatus_Fail;
913         }
914 
915         /* Prepare ivSeed for current region */
916         IvReg[0] = uuid[0];
917         IvReg[1] = uuid[1];
918         IvReg[2] = uuid[2] ^ region;
919         IvReg[3] = ivEraseCounter[region];
920 
921         /* Calculate IV as IvReg = AES_ECB_ENC(DUK_derived_key, {ctx_erase_counter, ctx_id}) */
922         status = PRINCE_CSS_calculate_iv(IvReg);
923         if (status != kStatus_Success)
924         {
925             return kStatus_Fail;
926         }
927 
928         /* Load IV into PRINCE registers */
929         status = PRINCE_SetRegionIV(PRINCE, (prince_region_t)region, (uint8_t *)IvReg);
930         if (status != kStatus_Success)
931         {
932             return kStatus_Fail;
933         }
934 
935         /* Lock region if required */
936         if ((lock[region] == 0x1u) || (lock[region] == 0x2u) || (lock[region] == 0x3u))
937         {
938             PRINCE_SetLock(PRINCE, (kPRINCE_Region0Lock << region));
939         }
940     }
941 
942     /* Break the main loop in case that error occured during PRINCE configuration */
943     if (status != kStatus_Success)
944     {
945         return kStatus_Fail;
946     }
947 
948     /* When ENC_ENABLE is set, reading from PRINCE-encrypted regions is disabled. */
949     /* For LPC55S36, the ENC_ENABLE is self-cleared after programming memory. */
950     PRINCE_EncryptDisable(PRINCE);
951     return status;
952 }
953 
PRINCE_CSS_generate_random(uint8_t * output,size_t outputByteLen)954 static status_t PRINCE_CSS_generate_random(uint8_t *output, size_t outputByteLen)
955 {
956     status_t status = kStatus_Fail;
957 
958     // PRNG needs to be initialized; this can be done by calling mcuxClCss_KeyDelete_Async
959     // (delete any key slot, can be empty)
960     MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_KeyDelete_Async(18));
961     // mcuxClCss_KeyDelete_Async is a flow-protected function: Check the protection token and the return value
962     if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_KeyDelete_Async) != token) || (MCUXCLCSS_STATUS_OK_WAIT != result))
963         return kStatus_Fail; // Expect that no error occurred, meaning that the mcuxClCss_KeyDelete_Async operation was
964                              // started.
965     MCUX_CSSL_FP_FUNCTION_CALL_END();
966 
967     // Wait for operation to finish
968     MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_WaitForOperation(MCUXCLCSS_ERROR_FLAGS_CLEAR));
969     // mcuxClCss_WaitForOperation is a flow-protected function: Check the protection token and the return value
970     if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_WaitForOperation) != token) || (MCUXCLCSS_STATUS_OK != result))
971         return kStatus_Fail; // Expect that no error occurred, meaning that the mcuxClCss_WaitForOperation operation was
972                              // started.
973     MCUX_CSSL_FP_FUNCTION_CALL_END();
974 
975     MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_Prng_GetRandom(output, outputByteLen));
976     if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_Prng_GetRandom) != token) || (MCUXCLCSS_STATUS_OK != result))
977         return kStatus_Fail;
978     MCUX_CSSL_FP_FUNCTION_CALL_END();
979 
980     status = kStatus_Success;
981     return status;
982 }
983 
PRINCE_CSS_check_key(uint8_t keyIdx,mcuxClCss_KeyProp_t * pKeyProp)984 static status_t PRINCE_CSS_check_key(uint8_t keyIdx, mcuxClCss_KeyProp_t *pKeyProp)
985 {
986     /* Check if CSS required keys are available in CSS keystore */
987     MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token,
988                                      mcuxClCss_GetKeyProperties(keyIdx, pKeyProp)); // Get key propertis from the CSS.
989     // mcuxClCss_GetKeyProperties is a flow-protected function: Check the protection token and the return value
990     if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_GetKeyProperties) != token) || (MCUXCLCSS_STATUS_OK != result))
991         return kStatus_Fail;
992     MCUX_CSSL_FP_FUNCTION_CALL_END();
993 
994     return kStatus_Success;
995 }
996 
PRINCE_CSS_gen_iv_key(void)997 static status_t PRINCE_CSS_gen_iv_key(void)
998 {
999     /* The NXP_DIE_MEM_IV_ENC_SK is not loaded and needs to be regenerated (power-down wakeup) */
1000     /* Set KDF mask and key properties for NXP_DIE_MEM_IV_ENC_SK */
1001     SYSCON->CSS_KDF_MASK            = SYSCON_CSS_KDF_MASK;
1002     static const uint32_t ddata2[3] = {0x62032504, 0x72f04280, 0x87a2bbae};
1003     mcuxClCss_KeyProp_t keyProp;
1004     /* Set key properties in structure */
1005     keyProp.word.value = CSS_CSS_KS2_ks2_uaes_MASK | CSS_CSS_KS2_ks2_fgp_MASK | CSS_CSS_KS2_ks2_kact_MASK;
1006     status_t status    = kStatus_Fail;
1007 
1008     /* Generate the key using CKDF */
1009     MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(
1010         result, token,
1011         mcuxClCss_Ckdf_Sp800108_Async((mcuxClCss_KeyIndex_t)0, (mcuxClCss_KeyIndex_t)NXP_DIE_MEM_IV_ENC_SK, keyProp,
1012                                       (uint8_t const *)ddata2));
1013     if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_Ckdf_Sp800108_Async) != token) && (MCUXCLCSS_STATUS_OK != result))
1014     {
1015         return kStatus_Fail;
1016     }
1017     MCUX_CSSL_FP_FUNCTION_CALL_END();
1018 
1019     /* Wait for CKDF to finish */
1020     MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_WaitForOperation(MCUXCLCSS_ERROR_FLAGS_CLEAR));
1021     if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_WaitForOperation) == token) && (MCUXCLCSS_STATUS_OK == result))
1022     {
1023         status = kStatus_Success;
1024     }
1025     MCUX_CSSL_FP_FUNCTION_CALL_END();
1026 
1027     return status;
1028 }
1029 
PRINCE_CSS_enable(void)1030 static status_t PRINCE_CSS_enable(void)
1031 {
1032     mcuxClCss_KeyProp_t key_properties;
1033     status_t status = kStatus_Fail;
1034 
1035     /* Enable CSS and related clocks */
1036     status = CSS_PowerDownWakeupInit(CSS);
1037     if (status != kStatus_Success)
1038     {
1039         return kStatus_Fail;
1040     }
1041 
1042     /* Check if MEM_ENC_SK key is available in CSS keystore */
1043     status = PRINCE_CSS_check_key(NXP_DIE_MEM_ENC_SK, &key_properties);
1044     if (status != kStatus_Success || key_properties.bits.kactv != 1u)
1045     {
1046         return kStatus_Fail;
1047     }
1048 
1049     /* Check if MEM_IV_ENC_SK key is available in CSS keystore */
1050     status = PRINCE_CSS_check_key(NXP_DIE_MEM_IV_ENC_SK, &key_properties);
1051     if (status != kStatus_Success || key_properties.bits.kactv != 1u)
1052     {
1053         return PRINCE_CSS_gen_iv_key();
1054     }
1055 
1056     return kStatus_Success;
1057 }
1058 
PRINCE_CSS_calculate_iv(uint32_t * IvReg)1059 static status_t PRINCE_CSS_calculate_iv(uint32_t *IvReg)
1060 {
1061     mcuxClCss_CipherOption_t cipherOptions = {0};
1062     status_t status                        = kStatus_Fail;
1063 
1064     /* Configure CSS for AES ECB-128, using NXP_DIE_MEM_IV_ENC_SK key */
1065     cipherOptions.bits.cphmde = MCUXCLCSS_CIPHERPARAM_ALGORITHM_AES_ECB;
1066     cipherOptions.bits.dcrpt  = MCUXCLCSS_CIPHER_ENCRYPT;
1067     cipherOptions.bits.extkey = MCUXCLCSS_CIPHER_INTERNAL_KEY;
1068 
1069     do
1070     {
1071         /* Calculate IV as IvReg = AES_ECB_ENC(NXP_DIE_MEM_IV_ENC_SK, ivSeed[127:0]) */
1072         /* ivSeed[127:0] = {UUID[96:0] ^ regionNumber[1:0], ivEraseCounter[31:0]} */
1073         MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(
1074             result, token,
1075             mcuxClCss_Cipher_Async(cipherOptions, (mcuxClCss_KeyIndex_t)NXP_DIE_MEM_IV_ENC_SK, NULL,
1076                                    MCUXCLCSS_CIPHER_KEY_SIZE_AES_128, (uint8_t *)IvReg, MCUXCLCSS_CIPHER_BLOCK_SIZE_AES,
1077                                    NULL, (uint8_t *)IvReg));
1078         if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_Cipher_Async) != token) || (MCUXCLCSS_STATUS_OK_WAIT != result))
1079             break;
1080         MCUX_CSSL_FP_FUNCTION_CALL_END();
1081 
1082         MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(
1083             result, token,
1084             mcuxClCss_WaitForOperation(
1085                 MCUXCLCSS_ERROR_FLAGS_CLEAR)); // Wait for the mcuxClCss_Enable_Async operation to complete.
1086         // mcuxClCss_WaitForOperation is a flow-protected function: Check the protection token and the return value
1087         if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_WaitForOperation) == token) && (MCUXCLCSS_STATUS_OK == result))
1088         {
1089             status = kStatus_Success;
1090         }
1091         MCUX_CSSL_FP_FUNCTION_CALL_END();
1092     } while (0);
1093 
1094     return status;
1095 }
1096 #endif /* defined(FSL_PRINCE_DRIVER_LPC55S3x) */
1097