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