Commit 14f7558113319025508e38fbd36ad057c56e3237
Committed by
Ye Li
1 parent
c2cf89d203
Exists in
smarc_8mq_lf_v2020.04
and in
4 other branches
MLK-21297 imx8: Add DEK blob encapsulation
Add DEK encapsulation support for imx8. The DEK blob is generated by the SECO through the SCFW API. Signed-off-by: Clement Faure <clement.faure@nxp.com> (cherry picked from commit b785e44ce2d042c51386dadb6ec6693344a16fc6)
Showing 4 changed files with 173 additions and 0 deletions Side-by-side Diff
arch/arm/include/asm/arch-imx8/image.h
arch/arm/mach-imx/Kconfig
... | ... | @@ -104,6 +104,7 @@ |
104 | 104 | bool "Support the 'dek_blob' command" |
105 | 105 | select IMX_CAAM_DEK_ENCAP if ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP |
106 | 106 | select IMX_OPTEE_DEK_ENCAP if ARCH_IMX8M |
107 | + select IMX_SECO_DEK_ENCAP if ARCH_IMX8 | |
107 | 108 | help |
108 | 109 | This enables the 'dek_blob' command which is used with the |
109 | 110 | Freescale secure boot mechanism. This command encapsulates and |
... | ... | @@ -124,6 +125,12 @@ |
124 | 125 | This enabled the DEK blob encapsulation with OP-TEE. The communication |
125 | 126 | with OP-TEE is done through a SMC call and OP-TEE shared memory. This |
126 | 127 | option is available on imx8mm. |
128 | + | |
129 | +config IMX_SECO_DEK_ENCAP | |
130 | + bool "Support the DEK blob encapsulation with SECO" | |
131 | + help | |
132 | + This enabled the DEK blob encapsulation with the SECO API. This option | |
133 | + is only available on imx8. | |
127 | 134 | |
128 | 135 | config CMD_PRIBLOB |
129 | 136 | bool "Support the set_priblob_bitfield command" |
arch/arm/mach-imx/cmd_dek.c
... | ... | @@ -14,6 +14,11 @@ |
14 | 14 | #include <asm/arch/clock.h> |
15 | 15 | #include <mapmem.h> |
16 | 16 | #include <tee.h> |
17 | +#ifdef CONFIG_IMX_SECO_DEK_ENCAP | |
18 | +#include <asm/arch/sci/sci.h> | |
19 | +#include <asm/arch/image.h> | |
20 | +#endif | |
21 | +#include <cpu_func.h> | |
17 | 22 | |
18 | 23 | /** |
19 | 24 | * blob_dek() - Encapsulate the DEK as a blob using CAM's Key |
... | ... | @@ -128,6 +133,155 @@ |
128 | 133 | return ret; |
129 | 134 | } |
130 | 135 | #endif /* CONFIG_IMX_OPTEE_DEK_ENCAP */ |
136 | +#ifdef CONFIG_IMX_SECO_DEK_ENCAP | |
137 | + | |
138 | +#define DEK_BLOB_KEY_ID 0x0 | |
139 | + | |
140 | +#define AHAB_PRIVATE_KEY 0x81 | |
141 | +#define AHAB_VERSION 0x00 | |
142 | +#define AHAB_MODE_CBC 0x67 | |
143 | +#define AHAB_ALG_AES 0x55 | |
144 | +#define AHAB_128_AES_KEY 0x10 | |
145 | +#define AHAB_192_AES_KEY 0x18 | |
146 | +#define AHAB_256_AES_KEY 0x20 | |
147 | +#define AHAB_FLAG_KEK 0x80 | |
148 | +#define AHAB_DEK_BLOB 0x01 | |
149 | + | |
150 | +#define DEK_BLOB_HDR_SIZE 8 | |
151 | +#define SECO_PT 2U | |
152 | + | |
153 | +static int blob_encap_dek(uint32_t src_addr, uint32_t dst_addr, uint32_t len) | |
154 | +{ | |
155 | + sc_err_t err; | |
156 | + sc_rm_mr_t mr_input, mr_output; | |
157 | + struct generate_key_blob_hdr hdr; | |
158 | + uint8_t in_size, out_size; | |
159 | + uint8_t *src_ptr, *dst_ptr; | |
160 | + int ret = 0; | |
161 | + int i; | |
162 | + | |
163 | + /* Set sizes */ | |
164 | + in_size = sizeof(struct generate_key_blob_hdr) + len / 8; | |
165 | + out_size = BLOB_SIZE(len / 8) + DEK_BLOB_HDR_SIZE; | |
166 | + | |
167 | + /* Get src and dst virtual addresses */ | |
168 | + src_ptr = map_sysmem(src_addr, in_size); | |
169 | + dst_ptr = map_sysmem(dst_addr, out_size); | |
170 | + | |
171 | + /* Check addr input */ | |
172 | + if (!(src_ptr && dst_ptr)) { | |
173 | + debug("src_addr or dst_addr invalid\n"); | |
174 | + return -1; | |
175 | + } | |
176 | + | |
177 | + /* Build key header */ | |
178 | + hdr.version = AHAB_VERSION; | |
179 | + hdr.length_lsb = sizeof(struct generate_key_blob_hdr) + len / 8; | |
180 | + hdr.length_msb = 0x00; | |
181 | + hdr.tag = AHAB_PRIVATE_KEY; | |
182 | + hdr.flags = AHAB_DEK_BLOB; | |
183 | + hdr.algorithm = AHAB_ALG_AES; | |
184 | + hdr.mode = AHAB_MODE_CBC; | |
185 | + | |
186 | + switch (len) { | |
187 | + case 128: | |
188 | + hdr.size = AHAB_128_AES_KEY; | |
189 | + break; | |
190 | + case 192: | |
191 | + hdr.size = AHAB_192_AES_KEY; | |
192 | + break; | |
193 | + case 256: | |
194 | + hdr.size = AHAB_256_AES_KEY; | |
195 | + break; | |
196 | + default: | |
197 | + /* Not supported */ | |
198 | + debug("Invalid DEK size. Valid sizes are 128, 192 and 256b\n"); | |
199 | + return -1; | |
200 | + } | |
201 | + | |
202 | + /* Build input message */ | |
203 | + memmove((void *)(src_ptr + sizeof(struct generate_key_blob_hdr)), | |
204 | + (void *)src_ptr, len / 8); | |
205 | + memcpy((void *)src_ptr, (void *)&hdr, | |
206 | + sizeof(struct generate_key_blob_hdr)); | |
207 | + | |
208 | + /* Flush the cache before triggering the CAAM DMA */ | |
209 | + flush_dcache_range(src_addr, src_addr + in_size); | |
210 | + | |
211 | + /* Find input memory region */ | |
212 | + err = sc_rm_find_memreg( | |
213 | + (-1), &mr_input, src_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1), | |
214 | + ALIGN(src_addr + in_size, CONFIG_SYS_CACHELINE_SIZE)); | |
215 | + if (err) { | |
216 | + printf("Error: find memory region 0x%X\n", src_addr); | |
217 | + return -ENOMEM; | |
218 | + } | |
219 | + | |
220 | + /* Find output memory region */ | |
221 | + err = sc_rm_find_memreg( | |
222 | + (-1), &mr_output, dst_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1), | |
223 | + ALIGN(dst_addr + out_size, CONFIG_SYS_CACHELINE_SIZE)); | |
224 | + if (err) { | |
225 | + printf("Error: find memory region 0x%X\n", dst_addr); | |
226 | + return -ENOMEM; | |
227 | + } | |
228 | + | |
229 | + /* Set memory region permissions for SECO */ | |
230 | + err = sc_rm_set_memreg_permissions(-1, mr_input, SECO_PT, | |
231 | + SC_RM_PERM_FULL); | |
232 | + if (err) { | |
233 | + printf("Set permission failed for input memory region\n"); | |
234 | + ret = -EPERM; | |
235 | + goto error; | |
236 | + } | |
237 | + | |
238 | + err = sc_rm_set_memreg_permissions(-1, mr_output, SECO_PT, | |
239 | + SC_RM_PERM_FULL); | |
240 | + if (err) { | |
241 | + printf("Set permission failed for output memory region\n"); | |
242 | + ret = -EPERM; | |
243 | + goto error; | |
244 | + } | |
245 | + | |
246 | + /* Flush output data before SECO operation */ | |
247 | + flush_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr + | |
248 | + roundup(out_size, ARCH_DMA_MINALIGN))); | |
249 | + | |
250 | + /* Generate DEK blob */ | |
251 | + err = sc_seco_gen_key_blob((-1), 0x0, src_addr, dst_addr, out_size); | |
252 | + if (err) { | |
253 | + ret = -EPERM; | |
254 | + goto error; | |
255 | + } | |
256 | + | |
257 | + /* Invalidate output buffer */ | |
258 | + invalidate_dcache_range((ulong)dst_ptr, (ulong)(dst_ptr + | |
259 | + roundup(out_size, ARCH_DMA_MINALIGN))); | |
260 | + | |
261 | + printf("DEK Blob\n"); | |
262 | + for (i = 0; i < DEK_BLOB_HDR_SIZE + BLOB_SIZE(len / 8); i++) | |
263 | + printf("%02X", dst_ptr[i]); | |
264 | + printf("\n"); | |
265 | + | |
266 | +error: | |
267 | + /* Remove memory region permission to SECO */ | |
268 | + err = sc_rm_set_memreg_permissions(-1, mr_input, SECO_PT, | |
269 | + SC_RM_PERM_NONE); | |
270 | + if (err) { | |
271 | + printf("Error: remove permission failed for input\n"); | |
272 | + ret = -EPERM; | |
273 | + } | |
274 | + | |
275 | + err = sc_rm_set_memreg_permissions(-1, mr_output, SECO_PT, | |
276 | + SC_RM_PERM_NONE); | |
277 | + if (err) { | |
278 | + printf("Error: remove permission failed for output\n"); | |
279 | + ret = -EPERM; | |
280 | + } | |
281 | + | |
282 | + return ret; | |
283 | +} | |
284 | +#endif /* CONFIG_IMX_SECO_DEK_ENCAP */ | |
131 | 285 | |
132 | 286 | /** |
133 | 287 | * do_dek_blob() - Handle the "dek_blob" command-line command |