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