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