diff options
Diffstat (limited to 'lib/libutee/tee_api_property.c')
-rw-r--r-- | lib/libutee/tee_api_property.c | 580 |
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; +} |