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