summaryrefslogtreecommitdiff
path: root/lib/libutee/tee_api_property.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libutee/tee_api_property.c')
-rw-r--r--lib/libutee/tee_api_property.c580
1 files changed, 580 insertions, 0 deletions
diff --git a/lib/libutee/tee_api_property.c b/lib/libutee/tee_api_property.c
new file mode 100644
index 0000000..0d24524
--- /dev/null
+++ b/lib/libutee/tee_api_property.c
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ * Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <printk.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tee_api_defines.h>
+#include <tee_api.h>
+#include <tee_api_types.h>
+#include <tee_arith_internal.h>
+#include <tee_internal_api_extensions.h>
+#include <tee_isocket.h>
+#include <user_ta_header.h>
+#include <utee_syscalls.h>
+#include <util.h>
+
+#include "string_ext.h"
+#include "base64.h"
+
+#define PROP_STR_MAX 80
+
+#define PROP_ENUMERATOR_NOT_STARTED 0xffffffff
+
+struct prop_enumerator {
+ uint32_t idx; /* current index */
+ TEE_PropSetHandle prop_set; /* part of TEE_PROPSET_xxx */
+};
+
+const struct user_ta_property tee_props[] = {
+ {
+ "gpd.tee.arith.maxBigIntSize",
+ USER_TA_PROP_TYPE_U32,
+ &(const uint32_t){TEE_MAX_NUMBER_OF_SUPPORTED_BITS}
+ },
+ {
+ "gpd.tee.sockets.version",
+ USER_TA_PROP_TYPE_U32,
+ &(const uint32_t){TEE_ISOCKET_VERSION}
+ },
+ {
+ "gpd.tee.sockets.tcp.version",
+ USER_TA_PROP_TYPE_U32,
+ &(const uint32_t){TEE_ISOCKET_VERSION}
+ },
+};
+
+static TEE_Result propset_get(TEE_PropSetHandle h,
+ const struct user_ta_property **eps,
+ size_t *eps_len)
+{
+ if (h == TEE_PROPSET_CURRENT_TA) {
+ *eps = ta_props;
+ *eps_len = ta_num_props;
+ } else if (h == TEE_PROPSET_CURRENT_CLIENT) {
+ *eps = NULL;
+ *eps_len = 0;
+ } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) {
+ *eps = tee_props;
+ *eps_len = ARRAY_SIZE(tee_props);
+ } else {
+ return TEE_ERROR_ITEM_NOT_FOUND;
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
+ enum user_ta_prop_type *type,
+ void *buf, uint32_t *len)
+{
+ size_t l;
+
+ *type = ep->type;
+ switch (*type) {
+ case USER_TA_PROP_TYPE_BOOL:
+ l = sizeof(uint32_t);
+ break;
+ case USER_TA_PROP_TYPE_U32:
+ l = sizeof(uint32_t);
+ break;
+ case USER_TA_PROP_TYPE_UUID:
+ l = sizeof(TEE_UUID);
+ break;
+ case USER_TA_PROP_TYPE_IDENTITY:
+ l = sizeof(TEE_Identity);
+ break;
+ case USER_TA_PROP_TYPE_STRING:
+ /* take the leading 0 into account */
+ l = strlen(ep->value) + 1;
+ break;
+ case USER_TA_PROP_TYPE_BINARY_BLOCK:
+ /*
+ * in case of TA property, a binary block is provided as a
+ * string, which is base64 encoded. We must first decode it,
+ * without taking into account the zero termination of the
+ * string
+ */
+ l = *len;
+ if (!base64_dec(ep->value, strlen(ep->value), buf, &l) &&
+ (l <= *len))
+ return TEE_ERROR_GENERIC;
+ if (*len < l) {
+ *len = l;
+ return TEE_ERROR_SHORT_BUFFER;
+ }
+
+ *len = l;
+ return TEE_SUCCESS;
+ default:
+ return TEE_ERROR_GENERIC;
+ }
+
+ if (*len < l) {
+ *len = l;
+ return TEE_ERROR_SHORT_BUFFER;
+ }
+
+ *len = l;
+ memcpy(buf, ep->value, l);
+ return TEE_SUCCESS;
+}
+
+static TEE_Result propget_get_property(TEE_PropSetHandle h, const char *name,
+ enum user_ta_prop_type *type,
+ void *buf, uint32_t *len)
+{
+ TEE_Result res;
+ const struct user_ta_property *eps;
+ size_t eps_len;
+ uint32_t prop_type;
+ uint32_t index;
+
+ if (h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT ||
+ h == TEE_PROPSET_TEE_IMPLEMENTATION) {
+ size_t n;
+
+ res = propset_get(h, &eps, &eps_len);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ for (n = 0; n < eps_len; n++) {
+ if (!strcmp(name, eps[n].name))
+ return propget_get_ext_prop(eps + n, type,
+ buf, len);
+ }
+
+ /* get the index from the name */
+ res = utee_get_property_name_to_index((unsigned long)h, name,
+ strlen(name) + 1, &index);
+ if (res != TEE_SUCCESS)
+ return res;
+ res = utee_get_property((unsigned long)h, index, NULL, NULL,
+ buf, len, &prop_type);
+ } else {
+ struct prop_enumerator *pe = (struct prop_enumerator *)h;
+ uint32_t idx = pe->idx;
+
+ if (idx == PROP_ENUMERATOR_NOT_STARTED)
+ return TEE_ERROR_ITEM_NOT_FOUND;
+
+ res = propset_get(pe->prop_set, &eps, &eps_len);
+ if (res != TEE_SUCCESS)
+ return res;
+
+ if (idx < eps_len)
+ return propget_get_ext_prop(eps + idx, type, buf, len);
+ idx -= eps_len;
+
+ res = utee_get_property((unsigned long)pe->prop_set, idx,
+ NULL, NULL, buf, len, &prop_type);
+ if (res == TEE_ERROR_ITEM_NOT_FOUND)
+ res = TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ *type = prop_type;
+ return res;
+}
+
+TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
+ const char *name, char *value,
+ uint32_t *value_len)
+{
+ TEE_Result res;
+ size_t l;
+ enum user_ta_prop_type type;
+ void *tmp_buf = 0;
+ uint32_t tmp_len;
+ uint32_t uint32_val;
+ TEE_Identity *p_identity_val;
+
+ if (!value || !value_len) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ tmp_len = *value_len;
+ if (tmp_len < sizeof(TEE_Identity))
+ tmp_len = sizeof(TEE_Identity);
+ tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!tmp_buf) {
+ res = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ res = propget_get_property(propsetOrEnumerator, name, &type,
+ tmp_buf, &tmp_len);
+ if (res != TEE_SUCCESS) {
+ if (res == TEE_ERROR_SHORT_BUFFER) {
+ if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) {
+ /*
+ * in this case, we must enlarge the buffer
+ * with the size of the of the base64 encoded
+ * see base64_enc() function
+ */
+ tmp_len = base64_enc_len(tmp_len);
+ }
+ *value_len = tmp_len;
+ }
+ goto out;
+ }
+
+ switch (type) {
+ case USER_TA_PROP_TYPE_BOOL:
+ uint32_val = *((uint32_t *)tmp_buf);
+ l = strlcpy(value, (uint32_val ? "true" : "false"),
+ *value_len);
+ break;
+
+ case USER_TA_PROP_TYPE_U32:
+ uint32_val = *((uint32_t *)tmp_buf);
+ l = snprintf(value, *value_len, "%u", uint32_val);
+ break;
+
+ case USER_TA_PROP_TYPE_UUID:
+ l = snprintk(value, *value_len, "%pUl", tmp_buf);
+ break;
+
+ case USER_TA_PROP_TYPE_IDENTITY:
+ p_identity_val = ((TEE_Identity *)tmp_buf);
+ l = snprintk(value, *value_len, "%u:%pUl",
+ p_identity_val->login,
+ (void *)(&(p_identity_val->uuid)));
+ break;
+
+ case USER_TA_PROP_TYPE_STRING:
+ l = strlcpy(value, tmp_buf, *value_len);
+ break;
+
+ case USER_TA_PROP_TYPE_BINARY_BLOCK:
+ l = *value_len; /* l includes the zero-termination */
+ if (!base64_enc(tmp_buf, tmp_len, value, &l) &&
+ (l <= *value_len)) {
+ res = TEE_ERROR_GENERIC;
+ goto out;
+ }
+ l--; /* remove the zero-termination that is added later */
+ break;
+
+ default:
+ res = TEE_ERROR_BAD_FORMAT;
+ goto out;
+ }
+
+ l++; /* include zero termination */
+
+ if (l > *value_len)
+ res = TEE_ERROR_SHORT_BUFFER;
+ *value_len = l;
+
+out:
+ if (tmp_buf)
+ TEE_Free(tmp_buf);
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_ITEM_NOT_FOUND &&
+ res != TEE_ERROR_SHORT_BUFFER)
+ TEE_Panic(0);
+
+ return res;
+}
+
+TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator,
+ const char *name, bool *value)
+{
+ TEE_Result res;
+ enum user_ta_prop_type type;
+ uint32_t uint32_val;
+ uint32_t uint32_len = sizeof(uint32_val);
+ if (value == NULL) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ type = USER_TA_PROP_TYPE_BOOL;
+ res = propget_get_property(propsetOrEnumerator, name, &type,
+ &uint32_val, &uint32_len);
+ if (type != USER_TA_PROP_TYPE_BOOL)
+ res = TEE_ERROR_BAD_FORMAT;
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ *value = !!uint32_val;
+
+out:
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_ITEM_NOT_FOUND &&
+ res != TEE_ERROR_BAD_FORMAT)
+ TEE_Panic(0);
+
+ return res;
+}
+
+TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator,
+ const char *name, uint32_t *value)
+{
+ TEE_Result res;
+ enum user_ta_prop_type type;
+ uint32_t uint32_len = sizeof(uint32_t);
+
+ if (!value) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ type = USER_TA_PROP_TYPE_U32;
+ res = propget_get_property(propsetOrEnumerator, name, &type,
+ value, &uint32_len);
+ if (type != USER_TA_PROP_TYPE_U32)
+ res = TEE_ERROR_BAD_FORMAT;
+
+out:
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_ITEM_NOT_FOUND &&
+ res != TEE_ERROR_BAD_FORMAT)
+ TEE_Panic(0);
+
+ return res;
+}
+
+TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator,
+ const char *name, void *value,
+ uint32_t *value_len)
+{
+ TEE_Result res;
+ enum user_ta_prop_type type;
+
+ if (!value || !value_len) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ type = USER_TA_PROP_TYPE_BINARY_BLOCK;
+ res = propget_get_property(propsetOrEnumerator, name, &type,
+ value, value_len);
+ if (type != USER_TA_PROP_TYPE_BINARY_BLOCK)
+ res = TEE_ERROR_BAD_FORMAT;
+
+out:
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_ITEM_NOT_FOUND &&
+ res != TEE_ERROR_BAD_FORMAT &&
+ res != TEE_ERROR_SHORT_BUFFER)
+ TEE_Panic(0);
+
+ return res;
+}
+
+TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator,
+ const char *name, TEE_UUID *value)
+{
+ TEE_Result res;
+ enum user_ta_prop_type type;
+ uint32_t uuid_len = sizeof(TEE_UUID);
+
+ if (!value) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ type = USER_TA_PROP_TYPE_UUID;
+ res = propget_get_property(propsetOrEnumerator, name, &type,
+ value, &uuid_len);
+ if (type != USER_TA_PROP_TYPE_UUID)
+ res = TEE_ERROR_BAD_FORMAT;
+
+out:
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_ITEM_NOT_FOUND &&
+ res != TEE_ERROR_BAD_FORMAT)
+ TEE_Panic(0);
+
+ return res;
+}
+
+TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator,
+ const char *name, TEE_Identity *value)
+{
+ TEE_Result res;
+ enum user_ta_prop_type type;
+ uint32_t identity_len = sizeof(TEE_Identity);
+
+ if (!value) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ type = USER_TA_PROP_TYPE_IDENTITY;
+ res = propget_get_property(propsetOrEnumerator, name, &type,
+ value, &identity_len);
+ if (type != USER_TA_PROP_TYPE_IDENTITY)
+ res = TEE_ERROR_BAD_FORMAT;
+
+out:
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_ITEM_NOT_FOUND &&
+ res != TEE_ERROR_BAD_FORMAT)
+ TEE_Panic(0);
+
+ return res;
+}
+
+TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator)
+{
+ TEE_Result res;
+ struct prop_enumerator *pe;
+
+ if (!enumerator) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto err;
+ }
+
+ pe = TEE_Malloc(sizeof(struct prop_enumerator),
+ TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (pe == NULL) {
+ res = TEE_ERROR_OUT_OF_MEMORY;
+ goto err;
+ }
+
+ *enumerator = (TEE_PropSetHandle) pe;
+ TEE_ResetPropertyEnumerator(*enumerator);
+
+ goto out;
+
+err:
+ if (res == TEE_ERROR_OUT_OF_MEMORY)
+ return res;
+ TEE_Panic(0);
+out:
+ return TEE_SUCCESS;
+}
+
+void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator)
+{
+ struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
+
+ pe->idx = PROP_ENUMERATOR_NOT_STARTED;
+}
+
+void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator)
+{
+ struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
+
+ TEE_Free(pe);
+}
+
+void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator,
+ TEE_PropSetHandle propSet)
+{
+ struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
+
+ if (!pe)
+ return;
+
+ pe->idx = 0;
+ pe->prop_set = propSet;
+}
+
+TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator,
+ void *name, uint32_t *name_len)
+{
+ TEE_Result res;
+ struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
+ const struct user_ta_property *eps;
+ size_t eps_len;
+ const char *str;
+ size_t bufferlen;
+
+ if (!pe || !name || !name_len) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto err;
+ }
+
+ bufferlen = *name_len;
+ res = propset_get(pe->prop_set, &eps, &eps_len);
+ if (res != TEE_SUCCESS)
+ goto err;
+
+ if (pe->idx < eps_len) {
+ str = eps[pe->idx].name;
+ bufferlen = strlcpy(name, str, *name_len) + 1;
+ if (bufferlen > *name_len)
+ res = TEE_ERROR_SHORT_BUFFER;
+ *name_len = bufferlen;
+ } else {
+ res = utee_get_property((unsigned long)pe->prop_set,
+ pe->idx - eps_len,
+ name, name_len, NULL, NULL, NULL);
+ if (res != TEE_SUCCESS)
+ goto err;
+ }
+
+err:
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_ITEM_NOT_FOUND &&
+ res != TEE_ERROR_SHORT_BUFFER)
+ TEE_Panic(0);
+ return res;
+}
+
+TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator)
+{
+ TEE_Result res;
+ struct prop_enumerator *pe = (struct prop_enumerator *)enumerator;
+ uint32_t next_idx;
+ const struct user_ta_property *eps;
+ size_t eps_len;
+
+ if (!pe) {
+ res = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) {
+ res = TEE_ERROR_ITEM_NOT_FOUND;
+ goto out;
+ }
+
+ res = propset_get(pe->prop_set, &eps, &eps_len);
+ if (res != TEE_SUCCESS)
+ goto out;
+
+ next_idx = pe->idx + 1;
+ pe->idx = next_idx;
+ if (next_idx < eps_len)
+ res = TEE_SUCCESS;
+ else
+ res = utee_get_property((unsigned long)pe->prop_set,
+ next_idx - eps_len,
+ NULL, NULL, NULL, NULL, NULL);
+
+out:
+ if (res != TEE_SUCCESS &&
+ res != TEE_ERROR_ITEM_NOT_FOUND)
+ TEE_Panic(0);
+ return res;
+}