blob: ed44df394b154bd2a7d371594ca740b461b7cbfa [file] [log] [blame]
Peng Fanf1e0f9f2019-09-25 08:11:14 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
Gaurav Jain8ecc0db2023-06-15 18:09:24 +08003 * Copyright 2018-2019, 2022 NXP
Peng Fanf1e0f9f2019-09-25 08:11:14 +00004 */
5
Simon Glassed38aef2020-05-10 11:40:03 -06006#include <command.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +00007#include <errno.h>
Sean Anderson952ed672023-10-14 16:47:44 -04008#include <imx_container.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060010#include <asm/global_data.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +000011#include <asm/io.h>
Peng Fan2e0644a2023-04-28 12:08:09 +080012#include <firmware/imx/sci/sci.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +000013#include <asm/mach-imx/sys_proto.h>
14#include <asm/arch-imx/cpu.h>
15#include <asm/arch/sys_proto.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +000016#include <console.h>
Oliver Grautef46161a2020-11-06 09:09:29 +010017#include <cpu_func.h>
Gaurav Jain8ecc0db2023-06-15 18:09:24 +080018#include "u-boot/sha256.h"
Ye Li185af302023-06-15 18:09:23 +080019#include <asm/mach-imx/ahab.h>
Peng Fanf1e0f9f2019-09-25 08:11:14 +000020
21DECLARE_GLOBAL_DATA_PTR;
22
23#define SEC_SECURE_RAM_BASE (0x31800000UL)
24#define SEC_SECURE_RAM_END_BASE (SEC_SECURE_RAM_BASE + 0xFFFFUL)
25#define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE (0x60000000UL)
26
27#define SECO_PT 2U
Gaurav Jain8ecc0db2023-06-15 18:09:24 +080028#define AHAB_HASH_TYPE_MASK 0x00000700
29#define AHAB_HASH_TYPE_SHA256 0
Peng Fanf1e0f9f2019-09-25 08:11:14 +000030
Ye Li185af302023-06-15 18:09:23 +080031int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length)
32{
33 int err;
34
35 memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)container,
36 ALIGN(length, CONFIG_SYS_CACHELINE_SIZE));
37
38 err = sc_seco_authenticate(-1, SC_SECO_AUTH_CONTAINER,
39 SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE);
40 if (err)
41 printf("Authenticate container hdr failed, return %d\n", err);
42
43 return err;
44}
45
46int ahab_auth_release(void)
47{
48 int err;
49
50 err = sc_seco_authenticate(-1, SC_SECO_REL_CONTAINER, 0);
51 if (err)
52 printf("Error: release container failed!\n");
53
54 return err;
55}
56
57int ahab_verify_cntr_image(struct boot_img_t *img, int image_index)
58{
59 sc_faddr_t start, end;
60 sc_rm_mr_t mr;
61 int err;
62 int ret = 0;
63
64 debug("img %d, dst 0x%llx, src 0x%x, size 0x%x\n",
65 image_index, img->dst, img->offset, img->size);
66
67 /* Find the memreg and set permission for seco pt */
68 err = sc_rm_find_memreg(-1, &mr,
69 img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1),
70 ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE) - 1);
71
72 if (err) {
73 printf("Error: can't find memreg for image load address 0x%llx, error %d\n",
74 img->dst, err);
75 return -ENOMEM;
76 }
77
78 err = sc_rm_get_memreg_info(-1, mr, &start, &end);
79 if (!err)
80 debug("memreg %u 0x%llx -- 0x%llx\n", mr, start, end);
81
82 err = sc_rm_set_memreg_permissions(-1, mr,
83 SECO_PT, SC_RM_PERM_FULL);
84 if (err) {
85 printf("Set permission failed for img %d, error %d\n",
86 image_index, err);
87 return -EPERM;
88 }
89
90 err = sc_seco_authenticate(-1, SC_SECO_VERIFY_IMAGE,
91 1 << image_index);
92 if (err) {
93 printf("Authenticate img %d failed, return %d\n",
94 image_index, err);
95 ret = -EIO;
96 }
97
98 err = sc_rm_set_memreg_permissions(-1, mr,
99 SECO_PT, SC_RM_PERM_NONE);
100 if (err) {
101 printf("Remove permission failed for img %d, error %d\n",
102 image_index, err);
103 ret = -EPERM;
104 }
105
106 return ret;
107}
108
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000109static inline bool check_in_dram(ulong addr)
110{
111 int i;
Masahiro Yamadaf7ed78b2020-06-26 15:13:33 +0900112 struct bd_info *bd = gd->bd;
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000113
114 for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
115 if (bd->bi_dram[i].size) {
116 if (addr >= bd->bi_dram[i].start &&
117 addr < (bd->bi_dram[i].start + bd->bi_dram[i].size))
118 return true;
119 }
120 }
121
122 return false;
123}
124
125int authenticate_os_container(ulong addr)
126{
127 struct container_hdr *phdr;
128 int i, ret = 0;
129 int err;
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000130 u16 length;
131 struct boot_img_t *img;
132 unsigned long s, e;
Gaurav Jain8ecc0db2023-06-15 18:09:24 +0800133#ifdef CONFIG_ARMV8_CE_SHA256
134 u8 hash_value[SHA256_SUM_LEN];
135#endif
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000136
137 if (addr % 4) {
138 puts("Error: Image's address is not 4 byte aligned\n");
139 return -EINVAL;
140 }
141
142 if (!check_in_dram(addr)) {
143 puts("Error: Image's address is invalid\n");
144 return -EINVAL;
145 }
146
147 phdr = (struct container_hdr *)addr;
Sean Andersonc5126682023-10-14 16:47:43 -0400148 if (!valid_container_hdr(phdr)) {
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000149 printf("Error: Wrong container header\n");
150 return -EFAULT;
151 }
152
153 if (!phdr->num_images) {
154 printf("Error: Wrong container, no image found\n");
155 return -EFAULT;
156 }
157
158 length = phdr->length_lsb + (phdr->length_msb << 8);
159
160 debug("container length %u\n", length);
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000161
Ye Li185af302023-06-15 18:09:23 +0800162 err = ahab_auth_cntr_hdr(phdr, length);
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000163 if (err) {
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000164 ret = -EIO;
165 goto exit;
166 }
167
168 /* Copy images to dest address */
169 for (i = 0; i < phdr->num_images; i++) {
170 img = (struct boot_img_t *)(addr +
171 sizeof(struct container_hdr) +
172 i * sizeof(struct boot_img_t));
173
Oliver Graute8ad653b2020-11-06 09:09:30 +0100174 debug("img %d, dst 0x%x, src 0x%lux, size 0x%x\n",
Seb Fagardc307ad02020-03-30 17:13:31 +0200175 i, (uint32_t) img->dst, img->offset + addr, img->size);
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000176
177 memcpy((void *)img->dst, (const void *)(img->offset + addr),
178 img->size);
179
180 s = img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
Peng Fan194dccc2020-04-22 15:36:34 +0800181 e = ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE) - 1;
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000182
183 flush_dcache_range(s, e);
184
Gaurav Jain8ecc0db2023-06-15 18:09:24 +0800185#ifdef CONFIG_ARMV8_CE_SHA256
186 if (((img->hab_flags & AHAB_HASH_TYPE_MASK) >> 8) == AHAB_HASH_TYPE_SHA256) {
187 sha256_csum_wd((void *)img->dst, img->size, hash_value, CHUNKSZ_SHA256);
188 err = memcmp(&img->hash, &hash_value, SHA256_SUM_LEN);
189 if (err) {
190 printf("img %d hash comparison failed, error %d\n", i, err);
191 ret = -EIO;
192 goto exit;
193 }
194 } else {
195#endif
196 ret = ahab_verify_cntr_image(img, i);
197 if (ret)
198 goto exit;
199#ifdef CONFIG_ARMV8_CE_SHA256
200 }
201#endif
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000202 }
203
204exit:
Ye Li185af302023-06-15 18:09:23 +0800205 ahab_auth_release();
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000206
207 return ret;
208}
209
Simon Glassed38aef2020-05-10 11:40:03 -0600210static int do_authenticate(struct cmd_tbl *cmdtp, int flag, int argc,
211 char *const argv[])
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000212{
213 ulong addr;
214
215 if (argc < 2)
216 return CMD_RET_USAGE;
217
Simon Glass3ff49ec2021-07-24 09:03:29 -0600218 addr = hextoul(argv[1], NULL);
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000219
220 printf("Authenticate OS container at 0x%lx\n", addr);
221
222 if (authenticate_os_container(addr))
223 return CMD_RET_FAILURE;
224
225 return CMD_RET_SUCCESS;
226}
227
228static void display_life_cycle(u16 lc)
229{
230 printf("Lifecycle: 0x%04X, ", lc);
231 switch (lc) {
232 case 0x1:
233 printf("Pristine\n\n");
234 break;
235 case 0x2:
236 printf("Fab\n\n");
237 break;
238 case 0x8:
239 printf("Open\n\n");
240 break;
241 case 0x20:
242 printf("NXP closed\n\n");
243 break;
244 case 0x80:
245 printf("OEM closed\n\n");
246 break;
247 case 0x100:
248 printf("Partial field return\n\n");
249 break;
250 case 0x200:
251 printf("Full field return\n\n");
252 break;
253 case 0x400:
254 printf("No return\n\n");
255 break;
256 default:
257 printf("Unknown\n\n");
258 break;
259 }
260}
261
262#define AHAB_AUTH_CONTAINER_REQ 0x87
263#define AHAB_VERIFY_IMAGE_REQ 0x88
264
265#define AHAB_NO_AUTHENTICATION_IND 0xee
266#define AHAB_BAD_KEY_HASH_IND 0xfa
267#define AHAB_INVALID_KEY_IND 0xf9
268#define AHAB_BAD_SIGNATURE_IND 0xf0
269#define AHAB_BAD_HASH_IND 0xf1
270
271static void display_ahab_auth_event(u32 event)
272{
273 u8 cmd = (event >> 16) & 0xff;
274 u8 resp_ind = (event >> 8) & 0xff;
275
276 switch (cmd) {
277 case AHAB_AUTH_CONTAINER_REQ:
278 printf("\tCMD = AHAB_AUTH_CONTAINER_REQ (0x%02X)\n", cmd);
279 printf("\tIND = ");
280 break;
281 case AHAB_VERIFY_IMAGE_REQ:
282 printf("\tCMD = AHAB_VERIFY_IMAGE_REQ (0x%02X)\n", cmd);
283 printf("\tIND = ");
284 break;
285 default:
286 return;
287 }
288
289 switch (resp_ind) {
290 case AHAB_NO_AUTHENTICATION_IND:
291 printf("AHAB_NO_AUTHENTICATION_IND (0x%02X)\n\n", resp_ind);
292 break;
293 case AHAB_BAD_KEY_HASH_IND:
294 printf("AHAB_BAD_KEY_HASH_IND (0x%02X)\n\n", resp_ind);
295 break;
296 case AHAB_INVALID_KEY_IND:
297 printf("AHAB_INVALID_KEY_IND (0x%02X)\n\n", resp_ind);
298 break;
299 case AHAB_BAD_SIGNATURE_IND:
300 printf("AHAB_BAD_SIGNATURE_IND (0x%02X)\n\n", resp_ind);
301 break;
302 case AHAB_BAD_HASH_IND:
303 printf("AHAB_BAD_HASH_IND (0x%02X)\n\n", resp_ind);
304 break;
305 default:
306 printf("Unknown Indicator (0x%02X)\n\n", resp_ind);
307 break;
308 }
309}
310
Simon Glassed38aef2020-05-10 11:40:03 -0600311static int do_ahab_status(struct cmd_tbl *cmdtp, int flag, int argc,
312 char *const argv[])
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000313{
314 int err;
315 u8 idx = 0U;
316 u32 event;
317 u16 lc;
318
319 err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
Peng Fan25b7eb42023-06-15 18:08:58 +0800320 if (err) {
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000321 printf("Error in get lifecycle\n");
322 return -EIO;
323 }
324
325 display_life_cycle(lc);
326
327 err = sc_seco_get_event(-1, idx, &event);
Peng Fan25b7eb42023-06-15 18:08:58 +0800328 while (!err) {
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000329 printf("SECO Event[%u] = 0x%08X\n", idx, event);
330 display_ahab_auth_event(event);
331
332 idx++;
333 err = sc_seco_get_event(-1, idx, &event);
334 }
335
336 if (idx == 0)
337 printf("No SECO Events Found!\n\n");
338
339 return 0;
340}
341
Igor Opaniuk33651ac2023-08-21 22:33:41 +0300342int ahab_close(void)
343{
344 int err;
345 u16 lc;
346
347 err = sc_seco_chip_info(-1, &lc, NULL, NULL, NULL);
348 if (err != SC_ERR_NONE) {
349 printf("Error in get lifecycle\n");
350 return -EIO;
351 }
352
353 if (lc != 0x20) {
354 puts("Current lifecycle is NOT NXP closed, can't move to OEM closed\n");
355 display_life_cycle(lc);
356 return -EPERM;
357 }
358
359 err = sc_seco_forward_lifecycle(-1, 16);
360 if (err != SC_ERR_NONE) {
361 printf("Error in forward lifecycle to OEM closed\n");
362 return -EIO;
363 }
364
365 return 0;
366}
367
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000368static int confirm_close(void)
369{
370 puts("Warning: Please ensure your sample is in NXP closed state, "
371 "OEM SRK hash has been fused, \n"
372 " and you are able to boot a signed image successfully "
373 "without any SECO events reported.\n"
374 " If not, your sample will be unrecoverable.\n"
375 "\nReally perform this operation? <y/N>\n");
376
377 if (confirm_yesno())
378 return 1;
379
380 puts("Ahab close aborted\n");
381 return 0;
382}
383
Simon Glassed38aef2020-05-10 11:40:03 -0600384static int do_ahab_close(struct cmd_tbl *cmdtp, int flag, int argc,
385 char *const argv[])
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000386{
Clément Pérone61e6bc2020-12-21 18:31:28 +0100387 int confirmed = argc >= 2 && !strcmp(argv[1], "-y");
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000388 int err;
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000389
Clément Pérone61e6bc2020-12-21 18:31:28 +0100390 if (!confirmed && !confirm_close())
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000391 return -EACCES;
392
Igor Opaniuk33651ac2023-08-21 22:33:41 +0300393 err = ahab_close();
Peng Fan25b7eb42023-06-15 18:08:58 +0800394 if (err) {
Igor Opaniuk33651ac2023-08-21 22:33:41 +0300395 printf("Change to OEM closed failed\n");
396 return err;
Peng Fanf1e0f9f2019-09-25 08:11:14 +0000397 }
398
399 printf("Change to OEM closed successfully\n");
400
401 return 0;
402}
403
404U_BOOT_CMD(auth_cntr, CONFIG_SYS_MAXARGS, 1, do_authenticate,
405 "autenticate OS container via AHAB",
406 "addr\n"
407 "addr - OS container hex address\n"
408);
409
410U_BOOT_CMD(ahab_status, CONFIG_SYS_MAXARGS, 1, do_ahab_status,
411 "display AHAB lifecycle and events from seco",
412 ""
413);
414
415U_BOOT_CMD(ahab_close, CONFIG_SYS_MAXARGS, 1, do_ahab_close,
416 "Change AHAB lifecycle to OEM closed",
417 ""
418);