1 /*
2  * Copyright (c) 2020-2021, Freescale Semiconductor, Inc.
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef FSL_IAP_KBP_H_
10 #define FSL_IAP_KBP_H_
11 
12 #include "fsl_common.h"
13 
14 /*!
15  * @addtogroup kb_driver
16  * @{
17  */
18 /*******************************************************************************
19  * Definitions
20  *******************************************************************************/
21 
22 /*! @brief ROM API status group number */
23 #define kStatusGroup_RomApi (108U)
24 
25 /*! @brief ROM API status codes. */
26 enum
27 {
28     kStatus_RomApiExecuteCompleted = kStatus_Success, /*!< ROM successfully process the whole sb file/boot image.*/
29     kStatus_RomApiNeedMoreData =
30         MAKE_STATUS(kStatusGroup_RomApi, 1), /*!< ROM needs more data to continue processing the boot image.*/
31     kStatus_RomApiBufferSizeNotEnough =
32         MAKE_STATUS(kStatusGroup_RomApi,
33                     2), /*!< The user buffer is not enough for use by Kboot during execution of the operation.*/
34     kStatus_RomApiInvalidBuffer =
35         MAKE_STATUS(kStatusGroup_RomApi, 3), /*!< The user buffer is not ok for sbloader or authentication.*/
36 };
37 
38 /*!
39  *  @brief Details of the operation to be performed by the ROM.
40  *
41  * The #kRomAuthenticateImage operation requires the entire signed image to be
42  * available to the application.
43  */
44 typedef enum _kb_operation
45 {
46     kRomAuthenticateImage = 1, /*!< Authenticate a signed image.*/
47     kRomLoadImage         = 2, /*!< Load SB file.*/
48     kRomOperationCount    = 3,
49 } kb_operation_t;
50 
51 /*!
52  * @brief Security constraint flags, Security profile flags.
53  */
54 enum _kb_security_profile
55 {
56     kKbootMinRSA4096 = (1 << 16),
57 };
58 
59 /*!
60  * @brief Memory region definition.
61  */
62 typedef struct _kb_region
63 {
64     uint32_t address;
65     uint32_t length;
66 } kb_region_t;
67 
68 /*!
69  * @brief User-provided options passed into kb_init().
70  *
71  * The buffer field is a pointer to memory provided by the caller for use by
72  * Kboot during execution of the operation. Minimum size is the size of each
73  * certificate in the chain plus 432 bytes additional per certificate.
74  *
75  * The profile field is a mask that specifies which features are required in
76  * the SB file or image being processed. This includes the minimum AES and RSA
77  * key sizes. See the _kb_security_profile enum for profile mask constants.
78  * The image being loaded or authenticated must match the profile or an error will
79  * be returned.
80  *
81  * minBuildNumber is an optional field that can be used to prevent version
82  * rollback. The API will check the build number of the image, and if it is less
83  * than minBuildNumber will fail with an error.
84  *
85  * maxImageLength is used to verify the offsetToCertificateBlockHeaderInBytes
86  * value at the beginning of a signed image. It should be set to the length of
87  * the SB file. If verifying an image in flash, it can be set to the internal
88  * flash size or a large number like 0x10000000.
89  *
90  * userRHK can optionally be used by the user to override the RHK in IFR. If
91  * userRHK is not NULL, it points to a 32-byte array containing the SHA-256 of
92  * the root certificate's RSA public key.
93  *
94  * The regions field points to an array of memory regions that the SB file being
95  * loaded is allowed to access. If regions is NULL, then all memory is
96  * accessible by the SB file. This feature is required to prevent a malicious
97  * image from erasing good code or RAM contents while it is being loaded, only
98  * for us to find that the image is inauthentic when we hit the end of the
99  * section.
100  *
101  * overrideSBBootSectionID lets the caller override the default section of the
102  * SB file that is processed during a kKbootLoadSB operation. By default,
103  * the section specified in the firstBootableSectionID field of the SB header
104  * is loaded. If overrideSBBootSectionID is non-zero, then the section with
105  * the given ID will be loaded instead.
106  *
107  * The userSBKEK field lets a user provide their own AES-256 key for unwrapping
108  * keys in an SB file during the kKbootLoadSB operation. userSBKEK should point
109  * to a 32-byte AES-256 key. If userSBKEK is NULL then the IFR SBKEK will be used.
110  * After kb_init() returns, the caller should zero out the data pointed to by
111  * userSBKEK, as the API will have installed the key in the CAU3.
112  */
113 
114 typedef struct _kb_load_sb
115 {
116     uint32_t profile;
117     uint32_t minBuildNumber;
118     uint32_t overrideSBBootSectionID;
119     uint32_t *userSBKEK;
120     uint32_t regionCount;
121     const kb_region_t *regions;
122 } kb_load_sb_t;
123 
124 typedef struct _kb_authenticate
125 {
126     uint32_t profile;
127     uint32_t minBuildNumber;
128     uint32_t maxImageLength;
129     uint32_t *userRHK;
130 } kb_authenticate_t;
131 
132 typedef struct _kb_options
133 {
134     uint32_t version; /*!< Should be set to kKbootApiVersion.*/
135     uint8_t *buffer;  /*!< Caller-provided buffer used by Kboot.*/
136     uint32_t bufferLength;
137     kb_operation_t op;
138     union
139     {
140         kb_authenticate_t authenticate; /*! Settings for kKbootAuthenticate operation.*/
141         kb_load_sb_t loadSB;            /*! Settings for kKbootLoadSB operation.*/
142     };
143 } kb_options_t;
144 
145 /*!
146  * @brief Interface to memory operations for one region of memory.
147  */
148 typedef struct _memory_region_interface
149 {
150     status_t (*init)(void);
151     status_t (*read)(uint32_t address, uint32_t length, uint8_t *buffer);
152     status_t (*write)(uint32_t address, uint32_t length, const uint8_t *buffer);
153     status_t (*fill)(uint32_t address, uint32_t length, uint32_t pattern);
154     status_t (*flush)(void);
155     status_t (*erase)(uint32_t address, uint32_t length);
156     status_t (*config)(uint32_t *buffer);
157     status_t (*erase_all)(void);
158 } memory_region_interface_t;
159 
160 /*!
161  * @brief Structure of a memory map entry.
162  */
163 typedef struct _memory_map_entry
164 {
165     uint32_t startAddress;
166     uint32_t endAddress;
167     uint32_t memoryProperty;
168     uint32_t memoryId;
169     const memory_region_interface_t *memoryInterface;
170 } memory_map_entry_t;
171 
172 typedef struct _kb_opaque_session_ref
173 {
174     kb_options_t context;
175     bool cau3Initialized;
176     memory_map_entry_t *memoryMap;
177 } kb_session_ref_t;
178 
179 /*******************************************************************************
180  * API
181  ******************************************************************************/
182 #if defined(__cplusplus)
183 extern "C" {
184 #endif
185 
186 /*!
187  * @brief Initialize ROM API for a given operation.
188  *
189  * Inits the ROM API based on the options provided by the application in the second
190  * argument. Every call to rom_init() should be paired with a call to rom_deinit().
191  *
192  * @retval #kStatus_Success API was executed successfully.
193  * @retval #kStatus_InvalidArgument An invalid argument is provided.
194  * @retval #kStatus_RomApiBufferSizeNotEnough The user buffer is not enough for use by Kboot during execution of the
195  * operation.
196  * @retval #kStatus_RomApiInvalidBuffer The user buffer is not ok for sbloader or authentication.
197  * @retval #kStatus_SKBOOT_Fail Return the failed status of secure boot.
198  * @retval #kStatus_SKBOOT_KeyStoreMarkerInvalid The key code for the particular PRINCE region is not present in the
199  * keystore
200  * @retval #kStatus_SKBOOT_Success Return the successful status of secure boot.
201  */
202 status_t kb_init(kb_session_ref_t **session, const kb_options_t *options);
203 
204 /*!
205  * @brief Cleans up the ROM API context.
206  *
207  * After this call, the context parameter can be reused for another operation
208  * by calling rom_init() again.
209  *
210  * @retval #kStatus_Success API was executed successfully
211  */
212 status_t kb_deinit(kb_session_ref_t *session);
213 
214 /*!
215  * Perform the operation configured during init.
216  *
217  * This application must call this API repeatedly, passing in sequential chunks of
218  * data from the boot image (SB file) that is to be processed. The ROM will perform
219  * the selected operation on this data and return. The application may call this
220  * function with as much or as little data as it wishes, which can be used to select
221  * the granularity of time given to the application in between executing the operation.
222  *
223  * @param session Current ROM context pointer.
224  * @param data Buffer of boot image data provided to the ROM by the application.
225  * @param dataLength Length in bytes of the data in the buffer provided to the ROM.
226  *
227  * @retval #kStatus_Success ROM successfully process the part of sb file/boot image.
228  * @retval #kStatus_RomApiExecuteCompleted ROM successfully process the whole sb file/boot image.
229  * @retval #kStatus_Fail An error occurred while executing the operation.
230  * @retval #kStatus_RomApiNeedMoreData No error occurred, but the ROM needs more data to
231  * continue processing the boot image.
232  * @retval #kStatus_RomApiBufferSizeNotEnough user buffer is not enough for
233  * use by Kboot during execution of the operation.
234  */
235 status_t kb_execute(kb_session_ref_t *session, const uint8_t *data, uint32_t dataLength);
236 
237 #if defined(__cplusplus)
238 }
239 #endif
240 
241 /*!
242  *@}
243  */
244 
245 #endif /* FSL_IAP_KBP_H_ */
246