// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * All rights reserved. * Copyright (c) 2022, Linaro Limited. */ #include #include #include #include #include #include #include "handle.h" #define ASSERT_PARAM_TYPE(pt) \ do { \ if ((pt) != param_type) \ return TEE_ERROR_BAD_PARAMETERS; \ } while (0) static struct handle_db op_db = HANDLE_DB_INITIALIZER; static struct handle_db obj_db = HANDLE_DB_INITIALIZER; static uint32_t op_handle_get(TEE_OperationHandle h) { int rc = handle_get(&op_db, h); if (rc < 0) { EMSG("Failed to allocate handle"); TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); } /* +1 since 0 (TEE_HANDLE_NULL) is invalid */ return rc + 1; } static TEE_OperationHandle op_handle_put(uint32_t val) { void *h = NULL; if (val) { h = handle_put(&op_db, val - 1); if (!h) { EMSG("Invalid handle 0x%"PRIx32, val); TEE_Panic(TEE_ERROR_BAD_PARAMETERS); } } return h; } static TEE_OperationHandle op_handle_lookup(uint32_t val) { void *h = NULL; if (val) { h = handle_lookup(&op_db, val - 1); if (!h) { EMSG("Invalid handle 0x%"PRIx32, val); TEE_Panic(TEE_ERROR_BAD_PARAMETERS); } } return h; } static uint32_t obj_handle_get(TEE_ObjectHandle h) { int rc = handle_get(&obj_db, h); if (rc < 0) { EMSG("Failed to allocate handle"); TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); } /* +1 since 0 (TEE_HANDLE_NULL) is invalid */ return rc + 1; } static TEE_ObjectHandle obj_handle_put(uint32_t val) { void *h = NULL; if (val) { h = handle_put(&obj_db, val - 1); if (!h) { EMSG("Invalid handle 0x%"PRIx32, val); TEE_Panic(TEE_ERROR_BAD_PARAMETERS); } } return h; } static TEE_ObjectHandle obj_handle_lookup(uint32_t val) { void *h = NULL; if (val) { h = handle_lookup(&obj_db, val - 1); if (!h) { EMSG("Invalid handle 0x%"PRIx32, val); TEE_Panic(TEE_ERROR_BAD_PARAMETERS); } } return h; } TEE_Result ta_entry_allocate_operation(uint32_t param_type, TEE_Param params[4]) { TEE_Result res = TEE_ERROR_GENERIC; TEE_OperationHandle op = TEE_HANDLE_NULL; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); res = TEE_AllocateOperation(&op, params[0].value.b, params[1].value.a, params[1].value.b); params[0].value.a = op_handle_get(op); return res; } TEE_Result ta_entry_free_operation(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_put(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); TEE_FreeOperation(op); return TEE_SUCCESS; } TEE_Result ta_entry_get_operation_info(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); if (params[1].memref.size < sizeof(TEE_OperationInfo)) return TEE_ERROR_SHORT_BUFFER; params[1].memref.size = sizeof(TEE_OperationInfo); TEE_GetOperationInfo(op, params[1].memref.buffer); return TEE_SUCCESS; } TEE_Result ta_entry_reset_operation(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); TEE_ResetOperation(op); return TEE_SUCCESS; } TEE_Result ta_entry_set_operation_key(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); TEE_ObjectHandle key = obj_handle_lookup(params[0].value.b); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); return TEE_SetOperationKey(op, key); } TEE_Result ta_entry_set_operation_key2(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); TEE_ObjectHandle key1 = obj_handle_lookup(params[0].value.b); TEE_ObjectHandle key2 = obj_handle_lookup(params[1].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); return TEE_SetOperationKey2(op, key1, key2); } TEE_Result ta_entry_copy_operation(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle dst = op_handle_lookup(params[0].value.a); TEE_OperationHandle src = op_handle_lookup(params[0].value.b); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); TEE_CopyOperation(dst, src); return TEE_SUCCESS; } TEE_Result ta_entry_digest_update(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); TEE_DigestUpdate(op, params[1].memref.buffer, params[1].memref.size); return TEE_SUCCESS; } TEE_Result ta_entry_digest_do_final(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); return TEE_DigestDoFinal(op, params[1].memref.buffer, params[1].memref.size, params[2].memref.buffer, ¶ms[2].memref.size); } TEE_Result ta_entry_cipher_init(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); void *buffer = NULL; size_t size = 0; if (param_type == TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { buffer = NULL; size = 0; } else if (param_type == TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { buffer = params[1].memref.buffer; size = params[1].memref.size; } else return TEE_ERROR_BAD_PARAMETERS; TEE_CipherInit(op, buffer, size); return TEE_SUCCESS; } TEE_Result ta_entry_cipher_update(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); return TEE_CipherUpdate(op, params[1].memref.buffer, params[1].memref.size, params[2].memref.buffer, ¶ms[2].memref.size); } TEE_Result ta_entry_cipher_do_final(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); return TEE_CipherDoFinal(op, params[1].memref.buffer, params[1].memref.size, params[2].memref.buffer, ¶ms[2].memref.size); } TEE_Result ta_entry_mac_init(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); void *buffer = NULL; size_t size = 0; if (param_type == TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { buffer = NULL; size = 0; } else if (param_type == TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { buffer = params[1].memref.buffer; size = params[1].memref.size; } else return TEE_ERROR_BAD_PARAMETERS; TEE_MACInit(op, buffer, size); return TEE_SUCCESS; } TEE_Result ta_entry_mac_update(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); TEE_MACUpdate(op, params[1].memref.buffer, params[1].memref.size); return TEE_SUCCESS; } TEE_Result ta_entry_mac_final_compute(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); return TEE_MACComputeFinal(op, params[1].memref.buffer, params[1].memref.size, params[2].memref.buffer, ¶ms[2].memref.size); } TEE_Result ta_entry_mac_final_compare(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE)); return TEE_MACCompareFinal(op, params[1].memref.buffer, params[1].memref.size, params[2].memref.buffer, params[2].memref.size); } TEE_Result ta_entry_allocate_transient_object(uint32_t param_type, TEE_Param params[4]) { TEE_Result res = TEE_ERROR_GENERIC; TEE_ObjectHandle o = TEE_HANDLE_NULL; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); res = TEE_AllocateTransientObject(params[0].value.a, params[0].value.b, &o); if (res == TEE_SUCCESS) params[1].value.a = obj_handle_get(o); return res; } TEE_Result ta_entry_free_transient_object(uint32_t param_type, TEE_Param params[4]) { TEE_ObjectHandle o = obj_handle_put(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); TEE_FreeTransientObject(o); return TEE_SUCCESS; } TEE_Result ta_entry_reset_transient_object(uint32_t param_type, TEE_Param params[4]) { TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); TEE_ResetTransientObject(o); return TEE_SUCCESS; } struct attr_packed { uint32_t id; uint32_t a; uint32_t b; }; static TEE_Result unpack_attrs(const uint8_t *buf, size_t blen, TEE_Attribute **attrs, uint32_t *attr_count) { TEE_Result res = TEE_SUCCESS; TEE_Attribute *a = NULL; const struct attr_packed *ap = NULL; size_t num_attrs = 0; const size_t num_attrs_size = sizeof(uint32_t); if (blen == 0) goto out; if (((uintptr_t)buf & 0x3) != 0 || blen < num_attrs_size) return TEE_ERROR_BAD_PARAMETERS; num_attrs = *(uint32_t *) (void *)buf; if ((blen - num_attrs_size) < (num_attrs * sizeof(*ap))) return TEE_ERROR_BAD_PARAMETERS; ap = (const struct attr_packed *)(const void *)(buf + num_attrs_size); if (num_attrs > 0) { size_t n; a = TEE_Malloc(num_attrs * sizeof(TEE_Attribute), 0); if (!a) return TEE_ERROR_OUT_OF_MEMORY; for (n = 0; n < num_attrs; n++) { uintptr_t p; a[n].attributeID = ap[n].id; if (ap[n].id & TEE_ATTR_FLAG_VALUE) { a[n].content.value.a = ap[n].a; a[n].content.value.b = ap[n].b; continue; } a[n].content.ref.length = ap[n].b; p = (uintptr_t)ap[n].a; if (p) { if ((p + a[n].content.ref.length) > blen) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } p += (uintptr_t)buf; } a[n].content.ref.buffer = (void *)p; } } res = TEE_SUCCESS; out: if (res == TEE_SUCCESS) { *attrs = a; *attr_count = num_attrs; } else { TEE_Free(a); } return res; } TEE_Result ta_entry_populate_transient_object(uint32_t param_type, TEE_Param params[4]) { TEE_Result res = TEE_ERROR_GENERIC; TEE_Attribute *attrs = NULL; uint32_t attr_count = 0; TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, &attrs, &attr_count); if (res != TEE_SUCCESS) return res; res = TEE_PopulateTransientObject(o, attrs, attr_count); TEE_Free(attrs); return res; } TEE_Result ta_entry_copy_object_attributes(uint32_t param_type, TEE_Param params[4]) { TEE_ObjectHandle dst = obj_handle_lookup(params[0].value.a); TEE_ObjectHandle src = obj_handle_lookup(params[0].value.b); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); return TEE_CopyObjectAttributes1(dst, src); } TEE_Result ta_entry_generate_key(uint32_t param_type, TEE_Param params[4]) { TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); TEE_Result res = TEE_ERROR_GENERIC; TEE_Attribute *attrs = NULL; uint32_t attr_count = 0; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, &attrs, &attr_count); if (res != TEE_SUCCESS) return res; res = TEE_GenerateKey(o, params[0].value.b, attrs, attr_count); TEE_Free(attrs); return res; } TEE_Result ta_entry_asymmetric_encrypt(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); TEE_Result res = TEE_ERROR_GENERIC; TEE_Attribute *attrs = NULL; uint32_t attr_count = 0; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT)); res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, &attrs, &attr_count); if (res != TEE_SUCCESS) return res; res = TEE_AsymmetricEncrypt(op, attrs, attr_count, params[2].memref.buffer, params[2].memref.size, params[3].memref.buffer, ¶ms[3].memref.size); TEE_Free(attrs); return res; } TEE_Result ta_entry_asymmetric_decrypt(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); TEE_Result res = TEE_ERROR_GENERIC; TEE_Attribute *attrs = NULL; uint32_t attr_count = 0; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT)); res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, &attrs, &attr_count); if (res != TEE_SUCCESS) return res; res = TEE_AsymmetricDecrypt(op, attrs, attr_count, params[2].memref.buffer, params[2].memref.size, params[3].memref.buffer, ¶ms[3].memref.size); TEE_Free(attrs); return res; } TEE_Result ta_entry_asymmetric_sign_digest(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); TEE_Result res = TEE_ERROR_GENERIC; TEE_Attribute *attrs = NULL; uint32_t attr_count = 0; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT)); res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, &attrs, &attr_count); if (res != TEE_SUCCESS) return res; res = TEE_AsymmetricSignDigest(op, attrs, attr_count, params[2].memref.buffer, params[2].memref.size, params[3].memref.buffer, ¶ms[3].memref.size); TEE_Free(attrs); return res; } TEE_Result ta_entry_asymmetric_verify_digest(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); TEE_Result res = TEE_ERROR_GENERIC; TEE_Attribute *attrs = NULL; uint32_t attr_count = 0; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT)); res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, &attrs, &attr_count); if (res != TEE_SUCCESS) return res; res = TEE_AsymmetricVerifyDigest(op, attrs, attr_count, params[2].memref.buffer, params[2].memref.size, params[3].memref.buffer, params[3].memref.size); TEE_Free(attrs); return res; } TEE_Result ta_entry_derive_key(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); TEE_ObjectHandle key = obj_handle_lookup(params[0].value.b); TEE_Result res = TEE_ERROR_GENERIC; TEE_Attribute *attrs = NULL; uint32_t attr_count = 0; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, &attrs, &attr_count); if (res != TEE_SUCCESS) return res; TEE_DeriveKey(op, attrs, attr_count, key); TEE_Free(attrs); return TEE_SUCCESS; } TEE_Result ta_entry_random_number_generate(uint32_t param_type, TEE_Param params[4]) { void *buf = NULL; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); buf = TEE_Malloc(params[0].memref.size, 0); if (!buf) return TEE_ERROR_OUT_OF_MEMORY; TEE_GenerateRandom(buf, params[0].memref.size); TEE_MemMove(params[0].memref.buffer, buf, params[0].memref.size); TEE_Free(buf); return TEE_SUCCESS; } TEE_Result ta_entry_ae_init(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE)); return TEE_AEInit(op, params[1].memref.buffer, params[1].memref.size, params[0].value.b * 8, /* tag_len in bits */ params[2].value.a, params[2].value.b); } TEE_Result ta_entry_ae_update_aad(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); TEE_AEUpdateAAD(op, params[1].memref.buffer, params[1].memref.size); return TEE_SUCCESS; } TEE_Result ta_entry_ae_update(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); TEE_AEUpdate(op, params[1].memref.buffer, params[1].memref.size, params[2].memref.buffer, ¶ms[2].memref.size); return TEE_SUCCESS; } TEE_Result ta_entry_ae_encrypt_final(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); TEE_Result res = TEE_ERROR_OUT_OF_MEMORY; void *b2 = NULL; void *b3 = NULL; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT)); b2 = TEE_Malloc(params[2].memref.size, 0); b3 = TEE_Malloc(params[3].memref.size, 0); if (!b2 || !b3) goto out; res = TEE_AEEncryptFinal(op, params[1].memref.buffer, params[1].memref.size, b2, ¶ms[2].memref.size, b3, ¶ms[3].memref.size); if (!res) { TEE_MemMove(params[2].memref.buffer, b2, params[2].memref.size); TEE_MemMove(params[3].memref.buffer, b3, params[3].memref.size); } out: TEE_Free(b2); TEE_Free(b3); return res; } TEE_Result ta_entry_ae_decrypt_final(uint32_t param_type, TEE_Param params[4]) { TEE_OperationHandle op = op_handle_lookup(params[0].value.a); TEE_Result res = TEE_ERROR_OUT_OF_MEMORY; void *b2 = NULL; void *b3 = NULL; ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_MEMREF_INPUT)); b2 = TEE_Malloc(params[2].memref.size, 0); b3 = TEE_Malloc(params[3].memref.size, 0); if (!b2 || !b3) goto out; TEE_MemMove(b3, params[3].memref.buffer, params[3].memref.size); res = TEE_AEDecryptFinal(op, params[1].memref.buffer, params[1].memref.size, b2, ¶ms[2].memref.size, b3, params[3].memref.size); if (!res) TEE_MemMove(params[2].memref.buffer, b2, params[2].memref.size); out: TEE_Free(b2); TEE_Free(b3); return res; } TEE_Result ta_entry_get_object_buffer_attribute(uint32_t param_type, TEE_Param params[4]) { TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); return TEE_GetObjectBufferAttribute(o, params[0].value.b, params[1].memref.buffer, ¶ms[1].memref.size); } TEE_Result ta_entry_get_object_value_attribute(uint32_t param_type, TEE_Param params[4]) { TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); return TEE_GetObjectValueAttribute(o, params[0].value.b, ¶ms[1].value.a, ¶ms[1].value.b); } TEE_Result ta_entry_is_algo_supported(uint32_t param_type, TEE_Param params[TEE_NUM_PARAMS]) { ASSERT_PARAM_TYPE(TEE_PARAM_TYPES (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); params[1].value.a = TEE_IsAlgorithmSupported(params[0].value.a, params[0].value.b); return TEE_SUCCESS; }