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