1 /* 2 * Copyright (c) 2022 Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * DRTM service 7 * 8 * Authors: 9 * Lucian Paul-Trifu <lucian.paultrifu@gmail.com> 10 * Brian Nezvadovitz <brinez@microsoft.com> 2021-02-01 11 */ 12 13 #include <stdint.h> 14 15 #include <arch.h> 16 #include <arch_helpers.h> 17 #include <common/bl_common.h> 18 #include <common/debug.h> 19 #include <common/runtime_svc.h> 20 #include <drivers/auth/crypto_mod.h> 21 #include "drtm_main.h" 22 #include <lib/psci/psci_lib.h> 23 #include <lib/xlat_tables/xlat_tables_v2.h> 24 #include <plat/common/platform.h> 25 #include <services/drtm_svc.h> 26 #include <platform_def.h> 27 28 /* Structure to store DRTM features specific to the platform. */ 29 static drtm_features_t plat_drtm_features; 30 31 /* DRTM-formatted memory map. */ 32 static drtm_memory_region_descriptor_table_t *plat_drtm_mem_map; 33 34 int drtm_setup(void) 35 { 36 bool rc; 37 const plat_drtm_tpm_features_t *plat_tpm_feat; 38 const plat_drtm_dma_prot_features_t *plat_dma_prot_feat; 39 uint64_t dlme_data_min_size; 40 41 INFO("DRTM service setup\n"); 42 43 /* Read boot PE ID from MPIDR */ 44 plat_drtm_features.boot_pe_id = read_mpidr_el1() & MPIDR_AFFINITY_MASK; 45 46 rc = drtm_dma_prot_init(); 47 if (rc) { 48 return INTERNAL_ERROR; 49 } 50 51 /* 52 * initialise the platform supported crypto module that will 53 * be used by the DRTM-service to calculate hash of DRTM- 54 * implementation specific components 55 */ 56 crypto_mod_init(); 57 58 /* Build DRTM-compatible address map. */ 59 plat_drtm_mem_map = drtm_build_address_map(); 60 if (plat_drtm_mem_map == NULL) { 61 return INTERNAL_ERROR; 62 } 63 64 /* Get DRTM features from platform hooks. */ 65 plat_tpm_feat = plat_drtm_get_tpm_features(); 66 if (plat_tpm_feat == NULL) { 67 return INTERNAL_ERROR; 68 } 69 70 plat_dma_prot_feat = plat_drtm_get_dma_prot_features(); 71 if (plat_dma_prot_feat == NULL) { 72 return INTERNAL_ERROR; 73 } 74 75 /* 76 * Add up minimum DLME data memory. 77 * 78 * For systems with complete DMA protection there is only one entry in 79 * the protected regions table. 80 */ 81 if (plat_dma_prot_feat->dma_protection_support == 82 ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_COMPLETE) { 83 dlme_data_min_size = 84 sizeof(drtm_memory_region_descriptor_table_t) + 85 sizeof(drtm_mem_region_t); 86 } else { 87 /* 88 * TODO set protected regions table size based on platform DMA 89 * protection configuration 90 */ 91 panic(); 92 } 93 94 dlme_data_min_size += (drtm_get_address_map_size() + 95 PLAT_DRTM_EVENT_LOG_MAX_SIZE + 96 plat_drtm_get_tcb_hash_table_size() + 97 plat_drtm_get_imp_def_dlme_region_size()); 98 99 dlme_data_min_size = page_align(dlme_data_min_size, UP)/PAGE_SIZE; 100 101 /* Fill out platform DRTM features structure */ 102 /* Only support default PCR schema (0x1) in this implementation. */ 103 ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(plat_drtm_features.tpm_features, 104 ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_DEFAULT); 105 ARM_DRTM_TPM_FEATURES_SET_TPM_HASH(plat_drtm_features.tpm_features, 106 plat_tpm_feat->tpm_based_hash_support); 107 ARM_DRTM_TPM_FEATURES_SET_FW_HASH(plat_drtm_features.tpm_features, 108 plat_tpm_feat->firmware_hash_algorithm); 109 ARM_DRTM_MIN_MEM_REQ_SET_MIN_DLME_DATA_SIZE(plat_drtm_features.minimum_memory_requirement, 110 dlme_data_min_size); 111 ARM_DRTM_MIN_MEM_REQ_SET_DCE_SIZE(plat_drtm_features.minimum_memory_requirement, 112 plat_drtm_get_min_size_normal_world_dce()); 113 ARM_DRTM_DMA_PROT_FEATURES_SET_MAX_REGIONS(plat_drtm_features.dma_prot_features, 114 plat_dma_prot_feat->max_num_mem_prot_regions); 115 ARM_DRTM_DMA_PROT_FEATURES_SET_DMA_SUPPORT(plat_drtm_features.dma_prot_features, 116 plat_dma_prot_feat->dma_protection_support); 117 ARM_DRTM_TCB_HASH_FEATURES_SET_MAX_NUM_HASHES(plat_drtm_features.tcb_hash_features, 118 plat_drtm_get_tcb_hash_features()); 119 120 return 0; 121 } 122 123 static inline uint64_t drtm_features_tpm(void *ctx) 124 { 125 SMC_RET2(ctx, 1ULL, /* TPM feature is supported */ 126 plat_drtm_features.tpm_features); 127 } 128 129 static inline uint64_t drtm_features_mem_req(void *ctx) 130 { 131 SMC_RET2(ctx, 1ULL, /* memory req Feature is supported */ 132 plat_drtm_features.minimum_memory_requirement); 133 } 134 135 static inline uint64_t drtm_features_boot_pe_id(void *ctx) 136 { 137 SMC_RET2(ctx, 1ULL, /* Boot PE feature is supported */ 138 plat_drtm_features.boot_pe_id); 139 } 140 141 static inline uint64_t drtm_features_dma_prot(void *ctx) 142 { 143 SMC_RET2(ctx, 1ULL, /* DMA protection feature is supported */ 144 plat_drtm_features.dma_prot_features); 145 } 146 147 static inline uint64_t drtm_features_tcb_hashes(void *ctx) 148 { 149 SMC_RET2(ctx, 1ULL, /* TCB hash feature is supported */ 150 plat_drtm_features.tcb_hash_features); 151 } 152 153 static enum drtm_retc drtm_dl_check_caller_el(void *ctx) 154 { 155 uint64_t spsr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_SPSR_EL3); 156 uint64_t dl_caller_el; 157 uint64_t dl_caller_aarch; 158 159 dl_caller_el = spsr_el3 >> MODE_EL_SHIFT & MODE_EL_MASK; 160 dl_caller_aarch = spsr_el3 >> MODE_RW_SHIFT & MODE_RW_MASK; 161 162 /* Caller's security state is checked from drtm_smc_handle function */ 163 164 /* Caller can be NS-EL2/EL1 */ 165 if (dl_caller_el == MODE_EL3) { 166 ERROR("DRTM: invalid launch from EL3\n"); 167 return DENIED; 168 } 169 170 if (dl_caller_aarch != MODE_RW_64) { 171 ERROR("DRTM: invalid launch from non-AArch64 execution state\n"); 172 return DENIED; 173 } 174 175 return SUCCESS; 176 } 177 178 static enum drtm_retc drtm_dl_check_cores(void) 179 { 180 bool running_on_single_core; 181 uint64_t this_pe_aff_value = read_mpidr_el1() & MPIDR_AFFINITY_MASK; 182 183 if (this_pe_aff_value != plat_drtm_features.boot_pe_id) { 184 ERROR("DRTM: invalid launch on a non-boot PE\n"); 185 return DENIED; 186 } 187 188 running_on_single_core = psci_is_last_on_cpu_safe(); 189 if (!running_on_single_core) { 190 ERROR("DRTM: invalid launch due to non-boot PE not being turned off\n"); 191 return DENIED; 192 } 193 194 return SUCCESS; 195 } 196 197 static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) 198 { 199 enum drtm_retc ret = SUCCESS; 200 201 /* Ensure that only boot PE is powered on */ 202 ret = drtm_dl_check_cores(); 203 if (ret != SUCCESS) { 204 SMC_RET1(handle, ret); 205 } 206 207 /* 208 * Ensure that execution state is AArch64 and the caller 209 * is highest non-secure exception level 210 */ 211 ret = drtm_dl_check_caller_el(handle); 212 if (ret != SUCCESS) { 213 SMC_RET1(handle, ret); 214 } 215 216 SMC_RET1(handle, ret); 217 } 218 219 uint64_t drtm_smc_handler(uint32_t smc_fid, 220 uint64_t x1, 221 uint64_t x2, 222 uint64_t x3, 223 uint64_t x4, 224 void *cookie, 225 void *handle, 226 uint64_t flags) 227 { 228 /* Check that the SMC call is from the Normal World. */ 229 if (!is_caller_non_secure(flags)) { 230 SMC_RET1(handle, NOT_SUPPORTED); 231 } 232 233 switch (smc_fid) { 234 case ARM_DRTM_SVC_VERSION: 235 INFO("DRTM service handler: version\n"); 236 /* Return the version of current implementation */ 237 SMC_RET1(handle, ARM_DRTM_VERSION); 238 break; /* not reached */ 239 240 case ARM_DRTM_SVC_FEATURES: 241 if (((x1 >> ARM_DRTM_FUNC_SHIFT) & ARM_DRTM_FUNC_MASK) == 242 ARM_DRTM_FUNC_ID) { 243 /* Dispatch function-based queries. */ 244 switch (x1 & FUNCID_MASK) { 245 case ARM_DRTM_SVC_VERSION: 246 SMC_RET1(handle, SUCCESS); 247 break; /* not reached */ 248 249 case ARM_DRTM_SVC_FEATURES: 250 SMC_RET1(handle, SUCCESS); 251 break; /* not reached */ 252 253 case ARM_DRTM_SVC_UNPROTECT_MEM: 254 SMC_RET1(handle, SUCCESS); 255 break; /* not reached */ 256 257 case ARM_DRTM_SVC_DYNAMIC_LAUNCH: 258 SMC_RET1(handle, SUCCESS); 259 break; /* not reached */ 260 261 case ARM_DRTM_SVC_CLOSE_LOCALITY: 262 WARN("ARM_DRTM_SVC_CLOSE_LOCALITY feature %s", 263 "is not supported\n"); 264 SMC_RET1(handle, NOT_SUPPORTED); 265 break; /* not reached */ 266 267 case ARM_DRTM_SVC_GET_ERROR: 268 SMC_RET1(handle, SUCCESS); 269 break; /* not reached */ 270 271 case ARM_DRTM_SVC_SET_ERROR: 272 SMC_RET1(handle, SUCCESS); 273 break; /* not reached */ 274 275 case ARM_DRTM_SVC_SET_TCB_HASH: 276 WARN("ARM_DRTM_SVC_TCB_HASH feature %s", 277 "is not supported\n"); 278 SMC_RET1(handle, NOT_SUPPORTED); 279 break; /* not reached */ 280 281 case ARM_DRTM_SVC_LOCK_TCB_HASH: 282 WARN("ARM_DRTM_SVC_LOCK_TCB_HASH feature %s", 283 "is not supported\n"); 284 SMC_RET1(handle, NOT_SUPPORTED); 285 break; /* not reached */ 286 287 default: 288 ERROR("Unknown DRTM service function\n"); 289 SMC_RET1(handle, NOT_SUPPORTED); 290 break; /* not reached */ 291 } 292 } else { 293 /* Dispatch feature-based queries. */ 294 switch (x1 & ARM_DRTM_FEAT_ID_MASK) { 295 case ARM_DRTM_FEATURES_TPM: 296 INFO("++ DRTM service handler: TPM features\n"); 297 return drtm_features_tpm(handle); 298 break; /* not reached */ 299 300 case ARM_DRTM_FEATURES_MEM_REQ: 301 INFO("++ DRTM service handler: Min. mem." 302 " requirement features\n"); 303 return drtm_features_mem_req(handle); 304 break; /* not reached */ 305 306 case ARM_DRTM_FEATURES_DMA_PROT: 307 INFO("++ DRTM service handler: " 308 "DMA protection features\n"); 309 return drtm_features_dma_prot(handle); 310 break; /* not reached */ 311 312 case ARM_DRTM_FEATURES_BOOT_PE_ID: 313 INFO("++ DRTM service handler: " 314 "Boot PE ID features\n"); 315 return drtm_features_boot_pe_id(handle); 316 break; /* not reached */ 317 318 case ARM_DRTM_FEATURES_TCB_HASHES: 319 INFO("++ DRTM service handler: " 320 "TCB-hashes features\n"); 321 return drtm_features_tcb_hashes(handle); 322 break; /* not reached */ 323 324 default: 325 ERROR("Unknown ARM DRTM service feature\n"); 326 SMC_RET1(handle, NOT_SUPPORTED); 327 break; /* not reached */ 328 } 329 } 330 331 case ARM_DRTM_SVC_UNPROTECT_MEM: 332 INFO("DRTM service handler: unprotect mem\n"); 333 SMC_RET1(handle, SMC_OK); 334 break; /* not reached */ 335 336 case ARM_DRTM_SVC_DYNAMIC_LAUNCH: 337 INFO("DRTM service handler: dynamic launch\n"); 338 return drtm_dynamic_launch(x1, handle); 339 break; /* not reached */ 340 341 case ARM_DRTM_SVC_CLOSE_LOCALITY: 342 WARN("DRTM service handler: close locality %s\n", 343 "is not supported"); 344 SMC_RET1(handle, NOT_SUPPORTED); 345 break; /* not reached */ 346 347 case ARM_DRTM_SVC_GET_ERROR: 348 INFO("DRTM service handler: get error\n"); 349 SMC_RET2(handle, SMC_OK, 0); 350 break; /* not reached */ 351 352 case ARM_DRTM_SVC_SET_ERROR: 353 INFO("DRTM service handler: set error\n"); 354 SMC_RET1(handle, SMC_OK); 355 break; /* not reached */ 356 357 case ARM_DRTM_SVC_SET_TCB_HASH: 358 WARN("DRTM service handler: set TCB hash %s\n", 359 "is not supported"); 360 SMC_RET1(handle, NOT_SUPPORTED); 361 break; /* not reached */ 362 363 case ARM_DRTM_SVC_LOCK_TCB_HASH: 364 WARN("DRTM service handler: lock TCB hash %s\n", 365 "is not supported"); 366 SMC_RET1(handle, NOT_SUPPORTED); 367 break; /* not reached */ 368 369 default: 370 ERROR("Unknown DRTM service function: 0x%x\n", smc_fid); 371 SMC_RET1(handle, SMC_UNK); 372 break; /* not reached */ 373 } 374 375 /* not reached */ 376 SMC_RET1(handle, SMC_UNK); 377 } 378