Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | // SPDX-License-Identifier: GPL-2.0+ /* * * Common security related functions for OMAP devices * * (C) Copyright 2016-2017 * Texas Instruments, <www.ti.com> * * Daniel Allred <d-allred@ti.com> * Andreas Dannenberg <dannenberg@ti.com> * Harinarayan Bhatta <harinarayan@ti.com> * Andrew F. Davis <afd@ti.com> */ #include <config.h> #include <command.h> #include <cpu_func.h> #include <hang.h> #include <init.h> #include <log.h> #include <stdarg.h> #include <asm/arch/sys_proto.h> #include <asm/cache.h> #include <asm/omap_common.h> #include <asm/omap_sec_common.h> #include <asm/spl.h> #include <asm/ti-common/sys_proto.h> #include <mapmem.h> #include <spl.h> #include <tee/optee.h> /* Index for signature verify ROM API */ #ifdef CONFIG_AM33XX #define API_HAL_KM_VERIFYCERTIFICATESIGNATURE_INDEX (0x0000000C) #else #define API_HAL_KM_VERIFYCERTIFICATESIGNATURE_INDEX (0x0000000E) #endif /* Index for signature PPA-based TI HAL APIs */ #define PPA_HAL_SERVICES_START_INDEX (0x200) #define PPA_SERV_HAL_TEE_LOAD_MASTER (PPA_HAL_SERVICES_START_INDEX + 23) #define PPA_SERV_HAL_TEE_LOAD_SLAVE (PPA_HAL_SERVICES_START_INDEX + 24) #define PPA_SERV_HAL_SETUP_SEC_RESVD_REGION (PPA_HAL_SERVICES_START_INDEX + 25) #define PPA_SERV_HAL_SETUP_EMIF_FW_REGION (PPA_HAL_SERVICES_START_INDEX + 26) #define PPA_SERV_HAL_LOCK_EMIF_FW (PPA_HAL_SERVICES_START_INDEX + 27) /* Offset of header size if image is signed as ISW */ #define HEADER_SIZE_OFFSET (0x6D) int tee_loaded = 0; /* Argument for PPA_SERV_HAL_TEE_LOAD_MASTER */ struct ppa_tee_load_info { u32 tee_sec_mem_start; /* Physical start address reserved for TEE */ u32 tee_sec_mem_size; /* Size of the memory reserved for TEE */ u32 tee_cert_start; /* Address where signed TEE binary is loaded */ u32 tee_cert_size; /* Size of TEE certificate (signed binary) */ u32 tee_jump_addr; /* Address to jump to start TEE execution */ u32 tee_arg0; /* argument to TEE jump function, in r0 */ }; static uint32_t secure_rom_call_args[5] __aligned(ARCH_DMA_MINALIGN) __section(".data"); u32 secure_rom_call(u32 service, u32 proc_id, u32 flag, ...) { int i; u32 num_args; va_list ap; va_start(ap, flag); num_args = va_arg(ap, u32); if (num_args > 4) { va_end(ap); return 1; } /* Copy args to aligned args structure */ for (i = 0; i < num_args; i++) secure_rom_call_args[i + 1] = va_arg(ap, u32); secure_rom_call_args[0] = num_args; va_end(ap); /* if data cache is enabled, flush the aligned args structure */ flush_dcache_range( (unsigned int)&secure_rom_call_args[0], (unsigned int)&secure_rom_call_args[0] + roundup(sizeof(secure_rom_call_args), ARCH_DMA_MINALIGN)); return omap_smc_sec(service, proc_id, flag, secure_rom_call_args); } static u32 find_sig_start(char *image, size_t size) { char *image_end = image + size; char *sig_start_magic = "CERT_"; int magic_str_len = strlen(sig_start_magic); char *ch; while (--image_end > image) { if (*image_end == '_') { ch = image_end - magic_str_len + 1; if (!strncmp(ch, sig_start_magic, magic_str_len)) return (u32)ch; } } return 0; } int secure_boot_verify_image(void **image, size_t *size) { int result = 1; u32 cert_addr, sig_addr; size_t cert_size; /* Perform cache writeback on input buffer */ flush_dcache_range( rounddown((u32)*image, ARCH_DMA_MINALIGN), roundup((u32)*image + *size, ARCH_DMA_MINALIGN)); cert_addr = (uint32_t)*image; sig_addr = find_sig_start((char *)*image, *size); if (sig_addr == 0) { printf("No signature found in image!\n"); result = 1; goto auth_exit; } *size = sig_addr - cert_addr; /* Subtract out the signature size */ /* Subtract header if present */ if (strncmp((char *)sig_addr, "CERT_ISW_", 9) == 0) *size -= ((u32 *)*image)[HEADER_SIZE_OFFSET]; cert_size = *size; /* Check if image load address is 32-bit aligned */ if (!IS_ALIGNED(cert_addr, 4)) { printf("Image is not 4-byte aligned!\n"); result = 1; goto auth_exit; } /* Image size also should be multiple of 4 */ if (!IS_ALIGNED(cert_size, 4)) { printf("Image size is not 4-byte aligned!\n"); result = 1; goto auth_exit; } /* Call ROM HAL API to verify certificate signature */ debug("%s: load_addr = %x, size = %x, sig_addr = %x\n", __func__, cert_addr, cert_size, sig_addr); result = secure_rom_call( API_HAL_KM_VERIFYCERTIFICATESIGNATURE_INDEX, 0, 0, 4, cert_addr, cert_size, sig_addr, 0xFFFFFFFF); /* Perform cache writeback on output buffer */ flush_dcache_range( rounddown((u32)*image, ARCH_DMA_MINALIGN), roundup((u32)*image + *size, ARCH_DMA_MINALIGN)); auth_exit: if (result != 0) { printf("Authentication failed!\n"); printf("Return Value = %08X\n", result); hang(); } /* * Output notification of successful authentication to re-assure the * user that the secure code is being processed as expected. However * suppress any such log output in case of building for SPL and booting * via YMODEM. This is done to avoid disturbing the YMODEM serial * protocol transactions. */ if (!(IS_ENABLED(CONFIG_XPL_BUILD) && IS_ENABLED(CONFIG_SPL_YMODEM_SUPPORT) && spl_boot_device() == BOOT_DEVICE_UART)) printf("Authentication passed\n"); return result; } u32 get_sec_mem_start(void) { u32 sec_mem_start = CONFIG_TI_SECURE_EMIF_REGION_START; u32 sec_mem_size = CONFIG_TI_SECURE_EMIF_TOTAL_REGION_SIZE; /* * Total reserved region is all contiguous with protected * region coming first, followed by the non-secure region. * If 0x0 start address is given, we simply put the reserved * region at the end of the external DRAM. */ if (sec_mem_start == 0) sec_mem_start = (CFG_SYS_SDRAM_BASE + ( #if defined(CONFIG_OMAP54XX) omap_sdram_size() #else get_ram_size((void *)CFG_SYS_SDRAM_BASE, CFG_MAX_RAM_BANK_SIZE) #endif - sec_mem_size)); return sec_mem_start; } int secure_emif_firewall_setup(uint8_t region_num, uint32_t start_addr, uint32_t size, uint32_t access_perm, uint32_t initiator_perm) { int result = 1; /* * Call PPA HAL API to do any other general firewall * configuration for regions 1-6 of the EMIF firewall. */ debug("%s: regionNum = %x, startAddr = %x, size = %x", __func__, region_num, start_addr, size); result = secure_rom_call( PPA_SERV_HAL_SETUP_EMIF_FW_REGION, 0, 0, 4, (start_addr & 0xFFFFFFF0) | (region_num & 0x0F), size, access_perm, initiator_perm); if (result != 0) { puts("Secure EMIF Firewall Setup failed!\n"); debug("Return Value = %x\n", result); } return result; } #if (CONFIG_TI_SECURE_EMIF_TOTAL_REGION_SIZE < \ CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE) #error "TI Secure EMIF: Protected size cannot be larger than total size." #endif int secure_emif_reserve(void) { int result = 1; u32 sec_mem_start = get_sec_mem_start(); u32 sec_prot_size = CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE; /* If there is no protected region, there is no reservation to make */ if (sec_prot_size == 0) return 0; /* * Call PPA HAL API to reserve a chunk of EMIF SDRAM * for secure world use. This region should be carved out * from use by any public code. EMIF firewall region 7 * will be used to protect this block of memory. */ result = secure_rom_call( PPA_SERV_HAL_SETUP_SEC_RESVD_REGION, 0, 0, 2, sec_mem_start, sec_prot_size); if (result != 0) { puts("SDRAM Firewall: Secure memory reservation failed!\n"); debug("Return Value = %x\n", result); } return result; } int secure_emif_firewall_lock(void) { int result = 1; /* * Call PPA HAL API to lock the EMIF firewall configurations. * After this API is called, none of the PPA HAL APIs for * configuring the EMIF firewalls will be usable again (that * is, calls to those APIs will return failure and have no * effect). */ result = secure_rom_call( PPA_SERV_HAL_LOCK_EMIF_FW, 0, 0, 0); if (result != 0) { puts("Secure EMIF Firewall Lock failed!\n"); debug("Return Value = %x\n", result); } return result; } static struct ppa_tee_load_info tee_info __aligned(ARCH_DMA_MINALIGN); int secure_tee_install(u32 addr) { struct optee_header *hdr; void *loadptr; u32 tee_file_size; u32 sec_mem_start = get_sec_mem_start(); const u32 size = CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE; u32 ret; /* If there is no protected region, there is no place to put the TEE */ if (size == 0) { printf("Error loading TEE, no protected memory region available\n"); return -ENOBUFS; } hdr = (struct optee_header *)map_sysmem(addr, sizeof(struct optee_header)); /* 280 bytes = size of signature */ tee_file_size = hdr->init_size + hdr->paged_size + sizeof(struct optee_header) + 280; if ((hdr->magic != OPTEE_MAGIC) || (hdr->version != OPTEE_VERSION) || (tee_file_size > size)) { printf("Error in TEE header. Check firewall and TEE sizes\n"); unmap_sysmem(hdr); return CMD_RET_FAILURE; } tee_info.tee_sec_mem_start = sec_mem_start; tee_info.tee_sec_mem_size = size; tee_info.tee_jump_addr = hdr->init_load_addr_lo; tee_info.tee_cert_start = addr; tee_info.tee_cert_size = tee_file_size; tee_info.tee_arg0 = hdr->init_size + tee_info.tee_jump_addr; unmap_sysmem(hdr); loadptr = map_sysmem(addr, tee_file_size); debug("tee_info.tee_sec_mem_start= %08X\n", tee_info.tee_sec_mem_start); debug("tee_info.tee_sec_mem_size = %08X\n", tee_info.tee_sec_mem_size); debug("tee_info.tee_jump_addr = %08X\n", tee_info.tee_jump_addr); debug("tee_info.tee_cert_start = %08X\n", tee_info.tee_cert_start); debug("tee_info.tee_cert_size = %08X\n", tee_info.tee_cert_size); debug("tee_info.tee_arg0 = %08X\n", tee_info.tee_arg0); debug("tee_file_size = %d\n", tee_file_size); #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) flush_dcache_range( rounddown((u32)loadptr, ARCH_DMA_MINALIGN), roundup((u32)loadptr + tee_file_size, ARCH_DMA_MINALIGN)); flush_dcache_range((u32)&tee_info, (u32)&tee_info + roundup(sizeof(tee_info), ARCH_DMA_MINALIGN)); #endif unmap_sysmem(loadptr); ret = secure_rom_call(PPA_SERV_HAL_TEE_LOAD_MASTER, 0, 0, 1, &tee_info); if (ret) { printf("TEE_LOAD_MASTER Failed\n"); return ret; } printf("TEE_LOAD_MASTER Done\n"); #if defined(CONFIG_OMAP54XX) if (!is_dra72x()) { u32 *smc_cpu1_params; /* Reuse the tee_info buffer for SMC params */ smc_cpu1_params = (u32 *)&tee_info; smc_cpu1_params[0] = 0; #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) flush_dcache_range((u32)smc_cpu1_params, (u32)smc_cpu1_params + roundup(sizeof(u32), ARCH_DMA_MINALIGN)); #endif ret = omap_smc_sec_cpu1(PPA_SERV_HAL_TEE_LOAD_SLAVE, 0, 0, smc_cpu1_params); if (ret) { printf("TEE_LOAD_SLAVE Failed\n"); return ret; } printf("TEE_LOAD_SLAVE Done\n"); } #endif tee_loaded = 1; return 0; } |