1 /*
2 * Copyright 2018 - 2023 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #ifndef FSL_PRINCE_H_
9 #define FSL_PRINCE_H_
10
11 #include "fsl_common.h"
12
13 #include FFR_INCLUDE
14
15 /*!
16 * @addtogroup prince
17 * @{
18 */
19
20 /*******************************************************************************
21 * Definitions
22 ******************************************************************************/
23
24 /*! @name Driver version */
25 /*! @{ */
26 /*! @brief PRINCE driver version 2.6.0.
27 *
28 * Current version: 2.6.0
29 *
30 * Change log:
31 * - Version 2.0.0
32 * - Initial version.
33 * - Version 2.1.0
34 * - Update for the A1 rev. of LPC55Sxx serie.
35 * - Version 2.2.0
36 * - Add runtime checking of the A0 and A1 rev. of LPC55Sxx serie to support
37 * both silicone revisions.
38 * - Version 2.3.0
39 * - Add support for LPC55S1x and LPC55S2x series
40 * - Version 2.3.0
41 * - Fix MISRA-2012 issues.
42 * - Version 2.3.1
43 * - Add support for LPC55S0x series
44 * - Version 2.3.2
45 * - Fix documentation of enumeration. Extend PRINCE example.
46 * - Version 2.4.0
47 * - Add support for LPC55S3x series
48 * - Version 2.5.0
49 * - Add PRINCE_Config() and PRINCE_Reconfig() features.
50 * - Version 2.5.1
51 * - Fix build error due to renamed symbols
52 * - Version 2.6.0
53 * - Renamed CSS to ELS
54 */
55 #define FSL_PRINCE_DRIVER_VERSION (MAKE_VERSION(2, 6, 0))
56 /*! @} */
57
58 #if (defined(LPC55S04_SERIES) || defined(LPC55S06_SERIES))
59 /* LPC55S0x series*/
60 #define FSL_PRINCE_DRIVER_LPC55S0x
61 #include "fsl_puf.h"
62
63 #elif (defined(LPC55S14_SERIES) || defined(LPC55S16_SERIES))
64 /* LPC55S1x series*/
65 #define FSL_PRINCE_DRIVER_LPC55S1x
66 #include "fsl_puf.h"
67
68 #elif (defined(LPC55S26_SERIES) || defined(LPC55S28_SERIES))
69 /* LPC55S2x series*/
70 #define FSL_PRINCE_DRIVER_LPC55S2x
71 #include "fsl_puf.h"
72
73 #elif (defined(LPC55S69_cm33_core0_SERIES) || defined(LPC55S69_cm33_core1_SERIES) || \
74 defined(LPC55S66_cm33_core0_SERIES) || defined(LPC55S66_cm33_core1_SERIES))
75 /* LPC55S6x series*/
76 #define FSL_PRINCE_DRIVER_LPC55S6x
77 #include "fsl_puf.h"
78
79 #elif (defined(LPC55S36_SERIES))
80 /* LPC55S3x series*/
81 #define FSL_PRINCE_DRIVER_LPC55S3x
82 #define PRINCE PRINCE0
83 #include "fsl_mem_interface.h"
84 #include "mcux_els.h" // Power Down Wake-up Init
85 #include <mcuxClEls.h> // Interface to the entire nxpClEls component
86 #include <mcuxCsslFlowProtection.h> // Code flow protection
87 #else
88 #error "No valid CPU defined!"
89 #endif
90
91 #define FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB (8U)
92 #define FSL_PRINCE_DRIVER_MAX_FLASH_ADDR \
93 ((uint32_t)FSL_FEATURE_SYSCON_FLASH_SIZE_BYTES - (FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 2U * 1024U))
94
95 #if !defined(ALIGN_DOWN)
96 #define ALIGN_DOWN(x, a) ((x) & (uint32_t)(-((int32_t)(a))))
97 #endif
98
99 /*! @brief Secure status enumeration. */
100 typedef enum _skboot_status
101 {
102 kStatus_SKBOOT_Success = 0x5ac3c35au, /*!< PRINCE Success */
103 kStatus_SKBOOT_Fail = 0xc35ac35au, /*!< PRINCE Fail */
104 kStatus_SKBOOT_InvalidArgument = 0xc35a5ac3u, /*!< PRINCE Invalid argument */
105 kStatus_SKBOOT_KeyStoreMarkerInvalid = 0xc3c35a5au, /*!< PRINCE Invalid marker */
106 } skboot_status_t;
107
108 /*! @brief Secure boolean enumeration. */
109 typedef enum _secure_bool
110 {
111 kSECURE_TRUE = 0xc33cc33cU, /*!< PRINCE true */
112 kSECURE_FALSE = 0x5aa55aa5U, /*!< PRINCE false */
113 } secure_bool_t;
114
115 /*! @brief Prince region. */
116 typedef enum _prince_region
117 {
118 kPRINCE_Region0 = 0U, /*!< PRINCE region 0 */
119 kPRINCE_Region1 = 1U, /*!< PRINCE region 1 */
120 kPRINCE_Region2 = 2U, /*!< PRINCE region 2 */
121 } prince_region_t;
122
123 /*! @brief Prince lock. */
124 typedef enum _prince_lock
125 {
126 kPRINCE_Region0Lock = 1U, /*!< PRINCE region 0 lock */
127 kPRINCE_Region1Lock = 2U, /*!< PRINCE region 1 lock */
128 kPRINCE_Region2Lock = 4U, /*!< PRINCE region 2 lock */
129 kPRINCE_MaskLock = 256U, /*!< PRINCE mask register lock */
130 } prince_lock_t;
131
132 /*! @brief Prince flag. */
133 typedef enum _prince_flags
134 {
135 kPRINCE_Flag_None = 0U, /*!< PRINCE Flag None */
136 kPRINCE_Flag_EraseCheck = 1U, /*!< PRINCE Flag Erase check */
137 kPRINCE_Flag_WriteCheck = 2U, /*!< PRINCE Flag Write check */
138 } prince_flags_t;
139
140 #if defined(FSL_PRINCE_DRIVER_LPC55S3x)
141 typedef struct
142 {
143 uint32_t target_prince_region : 2; // 0/1/2
144 uint32_t reserved : 22;
145 uint32_t tag : 8; // Fixed to 0x50 ('P')
146 } prince_prot_region_option_t;
147 typedef struct
148 {
149 prince_prot_region_option_t option;
150 uint32_t start;
151 uint32_t length;
152 } prince_prot_region_arg_t;
153
154 /*! @brief Prince fixed tag in prince_prot_region_option_t structure */
155 #define PRINCE_TAG 0x50u
156 #define PRINCE_TAG_SHIFT 24u
157 /*! @brief Prince region count */
158 #define PRINCE_REGION_COUNT 3u
159 /*! @brief Define for ELS key store indexes */
160 #define NXP_DIE_MEM_ENC_SK 2u
161 #define NXP_DIE_MEM_IV_ENC_SK 4u
162 /*! @brief KDF mask and key properties for NXP_DIE_MEM_IV_ENC_SK (see SYSCON documentation)*/
163 #define SYSCON_ELS_KDF_MASK 0x07000FCF
164 /*! @brief CFPA version and IV indexes (see Protected Flash Region table) */
165 #define CFPA_VER_OFFSET 0x04
166 #define CFPA_PRINCE_IV_OFFSET 0x14u
167 /*! @brief CMPA SR and lock indexes (see Protected Flash Region table) */
168 #define CMPA_PRINCE_SR_OFFSET 0x24u
169 #define CMPA_PRINCE_LOCK_OFFSET 0x20u
170 /*! @brief CFPA scrach version and IV addresses (see Protected Flash Region table) */
171 #define CFPA_SCRATCH_VER 0x3dc04
172 #define CFPA_SCRATCH_IV 0x3dc14
173 /*! @brief CMPA lock bit-field defines (see Protected Flash Region table) */
174 #define PRINCE_BASE_ADDR_LOCK_REG0_SHIFT (16u)
175 #define PRINCE_BASE_ADDR_LOCK_REG0_MASK (0x3u << PRINCE_BASE_ADDR_LOCK_REG0_SHIFT)
176 #define PRINCE_BASE_ADDR_LOCK_REG1_SHIFT (18u)
177 #define PRINCE_BASE_ADDR_LOCK_REG1_MASK (0x3u << PRINCE_BASE_ADDR_LOCK_REG1_SHIFT)
178 #define PRINCE_BASE_ADDR_LOCK_REG2_SHIFT (20u)
179 #define PRINCE_BASE_ADDR_LOCK_REG2_MASK (0x3u << PRINCE_BASE_ADDR_LOCK_REG2_SHIFT)
180
181 #endif /* defined(FSL_PRINCE_DRIVER_LPC55S3x) */
182
183 /*******************************************************************************
184 * API
185 ******************************************************************************/
186 #if defined(__cplusplus)
187 extern "C" {
188 #endif
189
190 /*!
191 * @brief Enable data encryption.
192 *
193 * This function enables PRINCE on-the-fly data encryption.
194 *
195 * @param base PRINCE peripheral address.
196 */
PRINCE_EncryptEnable(PRINCE_Type * base)197 static inline void PRINCE_EncryptEnable(PRINCE_Type *base)
198 {
199 base->ENC_ENABLE = 1u;
200 }
201
202 /*!
203 * @brief Disable data encryption.
204 *
205 * This function disables PRINCE on-the-fly data encryption.
206 *
207 * @param base PRINCE peripheral address.
208 */
PRINCE_EncryptDisable(PRINCE_Type * base)209 static inline void PRINCE_EncryptDisable(PRINCE_Type *base)
210 {
211 base->ENC_ENABLE = 0u;
212 }
213
214 /*!
215 * @brief Is Enable data encryption.
216 *
217 * This function test if PRINCE on-the-fly data encryption is enabled.
218 *
219 * @param base PRINCE peripheral address.
220 * @return true if enabled, false if not
221 */
PRINCE_IsEncryptEnable(PRINCE_Type * base)222 static inline bool PRINCE_IsEncryptEnable(PRINCE_Type *base)
223 {
224 return (base->ENC_ENABLE == 1u) ? true : false;
225 }
226
227 /*!
228 * @brief Sets PRINCE data mask.
229 *
230 * This function sets the PRINCE mask that is used to mask decrypted data.
231 *
232 * @param base PRINCE peripheral address.
233 * @param mask 64-bit data mask value.
234 */
PRINCE_SetMask(PRINCE_Type * base,uint64_t mask)235 static inline void PRINCE_SetMask(PRINCE_Type *base, uint64_t mask)
236 {
237 base->MASK_LSB = (uint32_t)(mask & 0xffffffffu);
238 base->MASK_MSB = (uint32_t)(mask >> 32u);
239 }
240
241 /*!
242 * @brief Locks access for specified region registers or data mask register.
243 *
244 * This function sets lock on specified region registers or mask register.
245 *
246 * @param base PRINCE peripheral address.
247 * @param lock registers to lock. This is a logical OR of members of the
248 * enumeration ::prince_lock_t
249 */
PRINCE_SetLock(PRINCE_Type * base,uint32_t lock)250 static inline void PRINCE_SetLock(PRINCE_Type *base, uint32_t lock)
251 {
252 base->LOCK = lock & 0x1ffu;
253 }
254
255 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
256 /*!
257 * @brief Generate new IV code.
258 *
259 * This function generates new IV code and stores it into the persistent memory.
260 * Ensure about 800 bytes free space on the stack when calling this routine with the store parameter set to true!
261 *
262 * @param region PRINCE region index.
263 * @param iv_code IV code pointer used for storing the newly generated 52 bytes long IV code.
264 * @param store flag to allow storing the newly generated IV code into the persistent memory (FFR).
265 * @param flash_context pointer to the flash driver context structure.
266 *
267 * @return kStatus_Success upon success
268 * @return kStatus_Fail otherwise, kStatus_Fail is also returned if the key code for the particular
269 * PRINCE region is not present in the keystore (though new IV code has been provided)
270 */
271 status_t PRINCE_GenNewIV(prince_region_t region, uint8_t *iv_code, bool store, flash_config_t *flash_context);
272 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
273
274 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
275 /*!
276 * @brief Load IV code.
277 *
278 * This function enables IV code loading into the PRINCE bus encryption engine.
279 *
280 * @param region PRINCE region index.
281 * @param iv_code IV code pointer used for passing the IV code.
282 *
283 * @return kStatus_Success upon success
284 * @return kStatus_Fail otherwise
285 */
286 status_t PRINCE_LoadIV(prince_region_t region, uint8_t *iv_code);
287 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
288
289 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
290 /*!
291 * @brief Allow encryption/decryption for specified address range.
292 *
293 * This function sets the encryption/decryption for specified address range.
294 * The SR mask value for the selected Prince region is calculated from provided
295 * start_address and length parameters. This calculated value is OR'ed with the
296 * actual SR mask value and stored into the PRINCE SR_ENABLE register and also
297 * into the persistent memory (FFR) to be used after the device reset. It is
298 * possible to define several nonadjacent encrypted areas within one Prince
299 * region when calling this function repeatedly. If the length parameter is set
300 * to 0, the SR mask value is set to 0 and thus the encryption/decryption for
301 * the whole selected Prince region is disabled.
302 * Ensure about 800 bytes free space on the stack when calling this routine!
303 *
304 * @param region PRINCE region index.
305 * @param start_address start address of the area to be encrypted/decrypted.
306 * @param length length of the area to be encrypted/decrypted.
307 * @param flash_context pointer to the flash driver context structure.
308 * @param regenerate_iv flag to allow IV code regenerating, storing into
309 * the persistent memory (FFR) and loading into the PRINCE engine
310 *
311 * @return kStatus_Success upon success
312 * @return kStatus_Fail otherwise
313 */
314 status_t PRINCE_SetEncryptForAddressRange(
315 prince_region_t region, uint32_t start_address, uint32_t length, flash_config_t *flash_context, bool regenerate_iv);
316 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
317
318 /*!
319 * @brief Gets the PRINCE Sub-Region Enable register.
320 *
321 * This function gets PRINCE SR_ENABLE register.
322 *
323 * @param base PRINCE peripheral address.
324 * @param region PRINCE region index.
325 * @param sr_enable Sub-Region Enable register pointer.
326 *
327 * @return kStatus_Success upon success
328 * @return kStatus_InvalidArgument
329 */
330 status_t PRINCE_GetRegionSREnable(PRINCE_Type *base, prince_region_t region, uint32_t *sr_enable);
331
332 /*!
333 * @brief Gets the PRINCE region base address register.
334 *
335 * This function gets PRINCE BASE_ADDR register.
336 *
337 * @param base PRINCE peripheral address.
338 * @param region PRINCE region index.
339 * @param region_base_addr Region base address pointer.
340 *
341 * @return kStatus_Success upon success
342 * @return kStatus_InvalidArgument
343 */
344 status_t PRINCE_GetRegionBaseAddress(PRINCE_Type *base, prince_region_t region, uint32_t *region_base_addr);
345
346 /*!
347 * @brief Sets the PRINCE region IV.
348 *
349 * This function sets specified AES IV for the given region.
350 *
351 * @param base PRINCE peripheral address.
352 * @param region Selection of the PRINCE region to be configured.
353 * @param iv 64-bit AES IV in little-endian byte order.
354 */
355 status_t PRINCE_SetRegionIV(PRINCE_Type *base, prince_region_t region, const uint8_t iv[8]);
356
357 /*!
358 * @brief Sets the PRINCE region base address.
359 *
360 * This function configures PRINCE region base address.
361 *
362 * @param base PRINCE peripheral address.
363 * @param region Selection of the PRINCE region to be configured.
364 * @param region_base_addr Base Address for region.
365 */
366 status_t PRINCE_SetRegionBaseAddress(PRINCE_Type *base, prince_region_t region, uint32_t region_base_addr);
367
368 /*!
369 * @brief Sets the PRINCE Sub-Region Enable register.
370 *
371 * This function configures PRINCE SR_ENABLE register.
372 *
373 * @param base PRINCE peripheral address.
374 * @param region Selection of the PRINCE region to be configured.
375 * @param sr_enable Sub-Region Enable register value.
376 */
377 status_t PRINCE_SetRegionSREnable(PRINCE_Type *base, prince_region_t region, uint32_t sr_enable);
378
379 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
380 /*!
381 * @brief Erases the flash sectors encompassed by parameters passed into function.
382 *
383 * This function erases the appropriate number of flash sectors based on the
384 * desired start address and length. It deals with the flash erase function
385 * complenentary to the standard erase API of the IAP1 driver. This implementation
386 * additionally checks if the whole encrypted PRINCE subregions are erased at once
387 * to avoid secrets revealing. The checker implementation is limited to one contiguous
388 * PRINCE-controlled memory area.
389 *
390 * @param config The pointer to the flash driver context structure.
391 * @param start The start address of the desired flash memory to be erased.
392 * The start address needs to be prince-sburegion-aligned.
393 * @param lengthInBytes The length, given in bytes (not words or long-words)
394 * to be erased. Must be prince-sburegion-size-aligned.
395 * @param key The value used to validate all flash erase APIs.
396 *
397 * @return #kStatus_FLASH_Success API was executed successfully.
398 * @return #kStatus_FLASH_InvalidArgument An invalid argument is provided.
399 * @return #kStatus_FLASH_AlignmentError The parameter is not aligned with the specified baseline.
400 * @return #kStatus_FLASH_AddressError The address is out of range.
401 * @return #kStatus_FLASH_EraseKeyError The API erase key is invalid.
402 * @return #kStatus_FLASH_CommandFailure Run-time error during the command execution.
403 * @return #kStatus_FLASH_CommandNotSupported Flash API is not supported.
404 * @return #kStatus_FLASH_EccError A correctable or uncorrectable error during command execution.
405 * @return #kStatus_FLASH_EncryptedRegionsEraseNotDoneAtOnce Encrypted flash subregions are not erased at once.
406 */
407 status_t PRINCE_FlashEraseWithChecker(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key);
408 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
409
410 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
411 /*!
412 * @brief Programs flash with data at locations passed in through parameters.
413 *
414 * This function programs the flash memory with the desired data for a given
415 * flash area as determined by the start address and the length. It deals with the
416 * flash program function complenentary to the standard program API of the IAP1 driver.
417 * This implementation additionally checks if the whole PRINCE subregions are
418 * programmed at once to avoid secrets revealing. The checker implementation is limited
419 * to one contiguous PRINCE-controlled memory area.
420 *
421 * @param config The pointer to the flash driver context structure.
422 * @param start The start address of the desired flash memory to be programmed. Must be
423 * prince-sburegion-aligned.
424 * @param src A pointer to the source buffer of data that is to be programmed
425 * into the flash.
426 * @param lengthInBytes The length, given in bytes (not words or long-words),
427 * to be programmed. Must be prince-sburegion-size-aligned.
428 *
429 * @return #kStatus_FLASH_Success API was executed successfully.
430 * @return #kStatus_FLASH_InvalidArgument An invalid argument is provided.
431 * @return #kStatus_FLASH_AlignmentError Parameter is not aligned with the specified baseline.
432 * @return #kStatus_FLASH_AddressError Address is out of range.
433 * @return #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses.
434 * @return #kStatus_FLASH_CommandFailure Run-time error during the command execution.
435 * @return #kStatus_FLASH_CommandFailure Run-time error during the command execution.
436 * @return #kStatus_FLASH_CommandNotSupported Flash API is not supported.
437 * @return #kStatus_FLASH_EccError A correctable or uncorrectable error during command execution.
438 * @return #kStatus_FLASH_SizeError Encrypted flash subregions are not programmed at once.
439 */
440 status_t PRINCE_FlashProgramWithChecker(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes);
441 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
442
443 #if defined(FSL_PRINCE_DRIVER_LPC55S3x)
444 /*!
445 * @brief Configures PRINCE setting.
446 *
447 * This function does the initial PRINCE configuration via ROM IAP API call.
448 * PRINCE_SR_x configuration for each region configuration is stored into FFR (CMPA).
449 * PRINCE IV erase counters (MCTR_INT_IV_CTRx) in CFPA are updated accordingly.
450 *
451 * Note: This function is expected to be called once in the device lifetime,
452 * typically during the initial device provisioning, since it is programming the CMPA pages in PFR flash.
453 *
454 * @param coreCtx The pointer to the ROM API driver context structure.
455 * @param config The pointer to the PRINCE driver configuration structure.
456 *
457 * @retval #kStatus_Success
458 * @retval #kStatus_CommandUnsupported
459 * @retval #kStatus_InvalidArgument
460 * @retval #kStatus_FLASH_ModifyProtectedAreaDisallowed
461 * @retval #kStatusMemoryRangeInvalid
462 * @retval #kStatus_Fail
463 * @retval #kStatus_OutOfRange
464 * @retval #kStatus_SPI_BaudrateNotSupport
465 */
466 status_t PRINCE_Configure(api_core_context_t *coreCtx, prince_prot_region_arg_t *config);
467 #endif /* defined(FSL_PRINCE_DRIVER_LPC55S3x) */
468
469 #if defined(FSL_PRINCE_DRIVER_LPC55S3x)
470 /*!
471 * @brief Reconfigures PRINCE setting.
472 *
473 * This function is used to re-configure PRINCE IP based on configuration stored in FFR.
474 * This function also needs to be called after wake up from power-down mode to regenerate IV
475 * encryption key in ELS key store whose presence is necessary for correct PRINCE operation
476 * during erase and write operations to encrypted regions of internal flash memory
477 * (dependency for correct operation of MEM_Erase() and MEM_Write() after wake up from power-down mode).
478 *
479 * @param coreCtx The pointer to the ROM API driver context structure.
480 *
481 * @retval #kStatus_Success
482 * @retval #kStatus_CommandUnsupported
483 * @retval #kStatus_InvalidArgument
484 * @retval #kStatus_FLASH_ModifyProtectedAreaDisallowed
485 * @retval #kStatusMemoryRangeInvalid
486 * @retval #kStatus_Fail
487 * @retval #kStatus_OutOfRange
488 * @retval #kStatus_SPI_BaudrateNotSupport
489 */
490 status_t PRINCE_Reconfigure(api_core_context_t *coreCtx);
491 #endif /* defined(FSL_PRINCE_DRIVER_LPC55S3x) */
492
493 #if (defined(FSL_PRINCE_DRIVER_LPC55S0x)) || defined(FSL_PRINCE_DRIVER_LPC55S1x) || defined(FSL_PRINCE_DRIVER_LPC55S3x)
494 /*!
495 * @brief Gets the PRINCE Error status register.
496 *
497 * @param base PRINCE peripheral address.
498 *
499 * @return PRINCE Error status register
500 */
PRINCE_GetErrorStatus(PRINCE_Type * base)501 static inline uint32_t PRINCE_GetErrorStatus(PRINCE_Type *base)
502 {
503 return base->ERR;
504 }
505
506 /*!
507 * @brief Clears the PRINCE Error status register.
508 *
509 * @param base PRINCE peripheral address.
510 */
PRINCE_ClearErrorStatus(PRINCE_Type * base)511 static inline void PRINCE_ClearErrorStatus(PRINCE_Type *base)
512 {
513 base->ERR = 0U;
514 }
515 #endif /* defined(FSL_PRINCE_DRIVER_LPC55S0x) || defined(FSL_PRINCE_DRIVER_LPC55S1x) || \
516 defined(FSL_PRINCE_DRIVER_LPC55S3x) */
517
518 #if defined(__cplusplus)
519 }
520 #endif
521
522 /*!
523 *@}
524 */
525
526 #endif /* FSL_PRINCE_H_ */
527