1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2018-2022 Linaro Limited 4 * Copyright (c) 2020, Arm Limited. 5 * Copyright (c) 2020, Open Mobile Platform LLC 6 */ 7 8 #include <assert.h> 9 #include <crypto/crypto.h> 10 #include <kernel/handle.h> 11 #include <kernel/huk_subkey.h> 12 #include <kernel/ldelf_loader.h> 13 #include <kernel/misc.h> 14 #include <kernel/msg_param.h> 15 #include <kernel/pseudo_ta.h> 16 #include <kernel/tpm.h> 17 #include <kernel/ts_store.h> 18 #include <kernel/user_access.h> 19 #include <kernel/user_mode_ctx.h> 20 #include <ldelf.h> 21 #include <mm/file.h> 22 #include <mm/fobj.h> 23 #include <mm/vm.h> 24 #include <pta_system.h> 25 #include <stdlib_ext.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <tee_api_defines_extensions.h> 29 #include <tee_api_defines.h> 30 #include <tee/tee_supp_plugin_rpc.h> 31 #include <tee/uuid.h> 32 #include <util.h> 33 34 static unsigned int system_pnum; 35 36 static TEE_Result system_rng_reseed(uint32_t param_types, 37 TEE_Param params[TEE_NUM_PARAMS]) 38 { 39 size_t entropy_sz = 0; 40 uint8_t *entropy_input = NULL; 41 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 42 TEE_PARAM_TYPE_NONE, 43 TEE_PARAM_TYPE_NONE, 44 TEE_PARAM_TYPE_NONE); 45 46 if (exp_pt != param_types) 47 return TEE_ERROR_BAD_PARAMETERS; 48 entropy_input = params[0].memref.buffer; 49 entropy_sz = params[0].memref.size; 50 51 if (!entropy_sz || !entropy_input) 52 return TEE_ERROR_BAD_PARAMETERS; 53 54 crypto_rng_add_event(CRYPTO_RNG_SRC_NONSECURE, &system_pnum, 55 entropy_input, entropy_sz); 56 return TEE_SUCCESS; 57 } 58 59 static TEE_Result system_derive_ta_unique_key(struct user_mode_ctx *uctx, 60 uint32_t param_types, 61 TEE_Param params[TEE_NUM_PARAMS]) 62 { 63 size_t data_len = sizeof(TEE_UUID); 64 TEE_Result res = TEE_ERROR_GENERIC; 65 uint8_t *data = NULL; 66 uint32_t access_flags = 0; 67 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 68 TEE_PARAM_TYPE_MEMREF_OUTPUT, 69 TEE_PARAM_TYPE_NONE, 70 TEE_PARAM_TYPE_NONE); 71 72 if (exp_pt != param_types) 73 return TEE_ERROR_BAD_PARAMETERS; 74 75 if (params[0].memref.size > TA_DERIVED_EXTRA_DATA_MAX_SIZE || 76 params[1].memref.size < TA_DERIVED_KEY_MIN_SIZE || 77 params[1].memref.size > TA_DERIVED_KEY_MAX_SIZE) 78 return TEE_ERROR_BAD_PARAMETERS; 79 80 /* 81 * The derived key shall not end up in non-secure memory by 82 * mistake. 83 * 84 * Note that we're allowing shared memory as long as it's 85 * secure. This is needed because a TA always uses shared memory 86 * when communicating with another TA. 87 */ 88 access_flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER | 89 TEE_MEMORY_ACCESS_SECURE; 90 res = vm_check_access_rights(uctx, access_flags, 91 (uaddr_t)params[1].memref.buffer, 92 params[1].memref.size); 93 if (res != TEE_SUCCESS) 94 return TEE_ERROR_SECURITY; 95 96 /* Take extra data into account. */ 97 if (ADD_OVERFLOW(data_len, params[0].memref.size, &data_len)) 98 return TEE_ERROR_SECURITY; 99 100 data = calloc(data_len, 1); 101 if (!data) 102 return TEE_ERROR_OUT_OF_MEMORY; 103 104 memcpy(data, &uctx->ts_ctx->uuid, sizeof(TEE_UUID)); 105 106 /* Append the user provided data */ 107 memcpy(data + sizeof(TEE_UUID), params[0].memref.buffer, 108 params[0].memref.size); 109 110 res = huk_subkey_derive(HUK_SUBKEY_UNIQUE_TA, data, data_len, 111 params[1].memref.buffer, 112 params[1].memref.size); 113 free_wipe(data); 114 115 return res; 116 } 117 118 static TEE_Result system_map_zi(struct user_mode_ctx *uctx, 119 uint32_t param_types, 120 TEE_Param params[TEE_NUM_PARAMS]) 121 { 122 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 123 TEE_PARAM_TYPE_VALUE_INOUT, 124 TEE_PARAM_TYPE_VALUE_INPUT, 125 TEE_PARAM_TYPE_NONE); 126 uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW; 127 TEE_Result res = TEE_ERROR_GENERIC; 128 struct mobj *mobj = NULL; 129 uint32_t pad_begin = 0; 130 uint32_t vm_flags = 0; 131 struct fobj *f = NULL; 132 uint32_t pad_end = 0; 133 size_t num_bytes = 0; 134 vaddr_t va = 0; 135 136 if (exp_pt != param_types) 137 return TEE_ERROR_BAD_PARAMETERS; 138 if (params[0].value.b & ~PTA_SYSTEM_MAP_FLAG_SHAREABLE) 139 return TEE_ERROR_BAD_PARAMETERS; 140 141 if (params[0].value.b & PTA_SYSTEM_MAP_FLAG_SHAREABLE) 142 vm_flags |= VM_FLAG_SHAREABLE; 143 144 num_bytes = params[0].value.a; 145 va = reg_pair_to_64(params[1].value.a, params[1].value.b); 146 pad_begin = params[2].value.a; 147 pad_end = params[2].value.b; 148 149 f = fobj_ta_mem_alloc(ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE)); 150 if (!f) 151 return TEE_ERROR_OUT_OF_MEMORY; 152 mobj = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); 153 fobj_put(f); 154 if (!mobj) 155 return TEE_ERROR_OUT_OF_MEMORY; 156 res = vm_map_pad(uctx, &va, num_bytes, prot, vm_flags, 157 mobj, 0, pad_begin, pad_end, 0); 158 mobj_put(mobj); 159 if (!res) 160 reg_pair_from_64(va, ¶ms[1].value.a, ¶ms[1].value.b); 161 162 return res; 163 } 164 165 static TEE_Result system_unmap(struct user_mode_ctx *uctx, uint32_t param_types, 166 TEE_Param params[TEE_NUM_PARAMS]) 167 { 168 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 169 TEE_PARAM_TYPE_VALUE_INPUT, 170 TEE_PARAM_TYPE_NONE, 171 TEE_PARAM_TYPE_NONE); 172 TEE_Result res = TEE_SUCCESS; 173 uint32_t vm_flags = 0; 174 vaddr_t end_va = 0; 175 vaddr_t va = 0; 176 size_t sz = 0; 177 178 if (exp_pt != param_types) 179 return TEE_ERROR_BAD_PARAMETERS; 180 181 if (params[0].value.b) 182 return TEE_ERROR_BAD_PARAMETERS; 183 184 va = reg_pair_to_64(params[1].value.a, params[1].value.b); 185 sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE); 186 187 /* 188 * The vm_get_flags() and vm_unmap() are supposed to detect or 189 * handle overflow directly or indirectly. However, this function 190 * an API function so an extra guard here is in order. If nothing 191 * else to make it easier to review the code. 192 */ 193 if (ADD_OVERFLOW(va, sz, &end_va)) 194 return TEE_ERROR_BAD_PARAMETERS; 195 196 res = vm_get_flags(uctx, va, sz, &vm_flags); 197 if (res) 198 return res; 199 if (vm_flags & VM_FLAG_PERMANENT) 200 return TEE_ERROR_ACCESS_DENIED; 201 202 return vm_unmap(uctx, va, sz); 203 } 204 205 static TEE_Result system_dlopen(struct user_mode_ctx *uctx, 206 uint32_t param_types, 207 TEE_Param params[TEE_NUM_PARAMS]) 208 { 209 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 210 TEE_PARAM_TYPE_VALUE_INPUT, 211 TEE_PARAM_TYPE_NONE, 212 TEE_PARAM_TYPE_NONE); 213 TEE_Result res = TEE_ERROR_GENERIC; 214 struct ts_session *s = NULL; 215 TEE_UUID uuid = { }; 216 uint32_t flags = 0; 217 218 if (exp_pt != param_types) 219 return TEE_ERROR_BAD_PARAMETERS; 220 221 if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid)) 222 return TEE_ERROR_BAD_PARAMETERS; 223 224 res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid)); 225 if (res) 226 return res; 227 228 flags = params[1].value.a; 229 230 s = ts_pop_current_session(); 231 res = ldelf_dlopen(uctx, &uuid, flags); 232 ts_push_current_session(s); 233 234 return res; 235 } 236 237 static TEE_Result system_dlsym(struct user_mode_ctx *uctx, uint32_t param_types, 238 TEE_Param params[TEE_NUM_PARAMS]) 239 { 240 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 241 TEE_PARAM_TYPE_MEMREF_INPUT, 242 TEE_PARAM_TYPE_VALUE_OUTPUT, 243 TEE_PARAM_TYPE_NONE); 244 TEE_Result res = TEE_ERROR_GENERIC; 245 struct ts_session *s = NULL; 246 char *sym = NULL; 247 TEE_UUID uuid = { }; 248 size_t symlen = 0; 249 vaddr_t va = 0; 250 251 if (exp_pt != param_types) 252 return TEE_ERROR_BAD_PARAMETERS; 253 254 if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid)) 255 return TEE_ERROR_BAD_PARAMETERS; 256 257 res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid)); 258 if (res) 259 return res; 260 261 if (!params[1].memref.buffer) 262 return TEE_ERROR_BAD_PARAMETERS; 263 res = bb_strndup_user(params[1].memref.buffer, params[1].memref.size, 264 &sym, &symlen); 265 if (res) 266 return res; 267 268 s = ts_pop_current_session(); 269 res = ldelf_dlsym(uctx, &uuid, sym, symlen, &va); 270 ts_push_current_session(s); 271 272 if (!res) 273 reg_pair_from_64(va, ¶ms[2].value.a, ¶ms[2].value.b); 274 275 return res; 276 } 277 278 static TEE_Result system_get_tpm_event_log(uint32_t param_types, 279 TEE_Param params[TEE_NUM_PARAMS]) 280 { 281 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 282 TEE_PARAM_TYPE_NONE, 283 TEE_PARAM_TYPE_NONE, 284 TEE_PARAM_TYPE_NONE); 285 size_t size = 0; 286 TEE_Result res = TEE_SUCCESS; 287 288 if (exp_pt != param_types) 289 return TEE_ERROR_BAD_PARAMETERS; 290 291 size = params[0].memref.size; 292 res = tpm_get_event_log(params[0].memref.buffer, &size); 293 params[0].memref.size = size; 294 295 return res; 296 } 297 298 static TEE_Result system_supp_plugin_invoke(uint32_t param_types, 299 TEE_Param params[TEE_NUM_PARAMS]) 300 { 301 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 302 TEE_PARAM_TYPE_VALUE_INPUT, 303 TEE_PARAM_TYPE_MEMREF_INOUT, 304 TEE_PARAM_TYPE_VALUE_OUTPUT); 305 TEE_Result res = TEE_ERROR_GENERIC; 306 size_t outlen = 0; 307 308 if (exp_pt != param_types) 309 return TEE_ERROR_BAD_PARAMETERS; 310 311 res = tee_invoke_supp_plugin_rpc(params[0].memref.buffer, /* uuid */ 312 params[1].value.a, /* cmd */ 313 params[1].value.b, /* sub_cmd */ 314 params[2].memref.buffer, /* data */ 315 params[2].memref.size, /* in len */ 316 &outlen); 317 params[3].value.a = (uint32_t)outlen; 318 319 return res; 320 } 321 322 static TEE_Result open_session(uint32_t param_types __unused, 323 TEE_Param params[TEE_NUM_PARAMS] __unused, 324 void **sess_ctx __unused) 325 { 326 struct ts_session *s = NULL; 327 328 /* Check that we're called from a user TA */ 329 s = ts_get_calling_session(); 330 if (!s) 331 return TEE_ERROR_ACCESS_DENIED; 332 if (!is_user_ta_ctx(s->ctx)) 333 return TEE_ERROR_ACCESS_DENIED; 334 335 return TEE_SUCCESS; 336 } 337 338 static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, 339 uint32_t param_types, 340 TEE_Param params[TEE_NUM_PARAMS]) 341 { 342 struct ts_session *s = ts_get_calling_session(); 343 struct user_mode_ctx *uctx = to_user_mode_ctx(s->ctx); 344 345 switch (cmd_id) { 346 case PTA_SYSTEM_ADD_RNG_ENTROPY: 347 return system_rng_reseed(param_types, params); 348 case PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY: 349 return system_derive_ta_unique_key(uctx, param_types, params); 350 case PTA_SYSTEM_MAP_ZI: 351 return system_map_zi(uctx, param_types, params); 352 case PTA_SYSTEM_UNMAP: 353 return system_unmap(uctx, param_types, params); 354 case PTA_SYSTEM_DLOPEN: 355 return system_dlopen(uctx, param_types, params); 356 case PTA_SYSTEM_DLSYM: 357 return system_dlsym(uctx, param_types, params); 358 case PTA_SYSTEM_GET_TPM_EVENT_LOG: 359 return system_get_tpm_event_log(param_types, params); 360 case PTA_SYSTEM_SUPP_PLUGIN_INVOKE: 361 return system_supp_plugin_invoke(param_types, params); 362 default: 363 break; 364 } 365 366 return TEE_ERROR_NOT_IMPLEMENTED; 367 } 368 369 pseudo_ta_register(.uuid = PTA_SYSTEM_UUID, .name = "system.pta", 370 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, 371 .open_session_entry_point = open_session, 372 .invoke_command_entry_point = invoke_command); 373