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