Commit eadf26f1834666e6ad3ab8f17556d5939c88549e

Authored by Jens Wiklander
Committed by Tom Rini
1 parent fe39e8e0ee

tee: add sandbox driver

Adds a sandbox tee driver which emulates a generic TEE with the OP-TEE
AVB TA.

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
[trini: Fix printf warnings in ta_avb_invoke_func, slots is uint]
Signed-off-by: Tom Rini <trini@konsulko.com>

Showing 5 changed files with 347 additions and 3 deletions Side-by-side Diff

1 1 # Generic Trusted Execution Environment Configuration
2 2 config TEE
3 3 bool "Trusted Execution Environment support"
4   - depends on ARM && (ARM64 || CPU_V7A)
5   - select ARM_SMCCC
  4 + depends on (ARM && (ARM64 || CPU_V7A)) || SANDBOX
  5 + select ARM_SMCCC if ARM
6 6 help
7 7 This implements a generic interface towards a Trusted Execution
8 8 Environment (TEE). A TEE is a trusted OS running in some secure
... ... @@ -13,6 +13,20 @@
13 13 if TEE
14 14  
15 15 menu "TEE drivers"
  16 +
  17 +config SANDBOX_TEE
  18 + bool "Sandbox TEE emulator"
  19 + depends on SANDBOX
  20 + default y
  21 + help
  22 + This emulates a generic TEE needed for testing including the AVB
  23 + TA. The emulation provides all callbacks of a regular TEE and
  24 + supports session and shared memory management. The AVB TA is
  25 + emulated with rollback indexes and device lock-state, the state
  26 + of the TA is only kept in RAM and will be reset on each boot.
  27 + The emulation only supports one open session at a time.
  28 + Interaction from the U-Boot command line in possible via the
  29 + "avb" commands.
16 30  
17 31 source "drivers/tee/optee/Kconfig"
18 32  
drivers/tee/Makefile
1 1 # SPDX-License-Identifier: GPL-2.0+
2 2  
3 3 obj-y += tee-uclass.o
  4 +obj-$(CONFIG_SANDBOX) += sandbox.o
4 5 obj-$(CONFIG_OPTEE) += optee/
drivers/tee/optee/Kconfig
... ... @@ -10,7 +10,7 @@
10 10 handle Remote Procedure Calls (RPC) from OP-TEE needed to
11 11 execute a service. For more information see: https://www.op-tee.org
12 12  
13   -if OPTEE
  13 +if OPTEE || SANDBOX
14 14  
15 15 menu "OP-TEE options"
16 16  
drivers/tee/sandbox.c
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * Copyright (C) 2018 Linaro Limited
  4 + */
  5 +#include <common.h>
  6 +#include <dm.h>
  7 +#include <sandboxtee.h>
  8 +#include <tee.h>
  9 +#include <tee/optee_ta_avb.h>
  10 +
  11 +/*
  12 + * The sandbox tee driver tries to emulate a generic Trusted Exectution
  13 + * Environment (TEE) with the Trusted Application (TA) OPTEE_TA_AVB
  14 + * available.
  15 + */
  16 +
  17 +/**
  18 + * struct ta_entry - TA entries
  19 + * @uuid: UUID of an emulated TA
  20 + * @open_session Called when a session is openened to the TA
  21 + * @invoke_func Called when a function in the TA is to be invoked
  22 + *
  23 + * This struct is used to register TAs in this sandbox emulation of a TEE.
  24 + */
  25 +struct ta_entry {
  26 + struct tee_optee_ta_uuid uuid;
  27 + u32 (*open_session)(uint num_params, struct tee_param *params);
  28 + u32 (*invoke_func)(u32 func, uint num_params, struct tee_param *params);
  29 +};
  30 +
  31 +#ifdef CONFIG_OPTEE_TA_AVB
  32 +static u32 get_attr(uint n, uint num_params, struct tee_param *params)
  33 +{
  34 + if (n >= num_params)
  35 + return TEE_PARAM_ATTR_TYPE_NONE;
  36 +
  37 + return params[n].attr;
  38 +}
  39 +
  40 +static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
  41 + struct tee_param *params)
  42 +{
  43 + u8 p[] = { p0, p1, p2, p3};
  44 + uint n;
  45 +
  46 + for (n = 0; n < ARRAY_SIZE(p); n++)
  47 + if (p[n] != get_attr(n, num_params, params))
  48 + goto bad_params;
  49 +
  50 + for (; n < num_params; n++)
  51 + if (get_attr(n, num_params, params))
  52 + goto bad_params;
  53 +
  54 + return TEE_SUCCESS;
  55 +
  56 +bad_params:
  57 + printf("Bad param attrs\n");
  58 +
  59 + return TEE_ERROR_BAD_PARAMETERS;
  60 +}
  61 +
  62 +static u64 ta_avb_rollback_indexes[TA_AVB_MAX_ROLLBACK_LOCATIONS];
  63 +static u32 ta_avb_lock_state;
  64 +
  65 +static u32 ta_avb_open_session(uint num_params, struct tee_param *params)
  66 +{
  67 + /*
  68 + * We don't expect additional parameters when opening a session to
  69 + * this TA.
  70 + */
  71 + return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
  72 + TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
  73 + num_params, params);
  74 +}
  75 +
  76 +static u32 ta_avb_invoke_func(u32 func, uint num_params,
  77 + struct tee_param *params)
  78 +{
  79 + u32 res;
  80 + uint slot;
  81 + u64 val;
  82 +
  83 + switch (func) {
  84 + case TA_AVB_CMD_READ_ROLLBACK_INDEX:
  85 + res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
  86 + TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
  87 + TEE_PARAM_ATTR_TYPE_NONE,
  88 + TEE_PARAM_ATTR_TYPE_NONE,
  89 + num_params, params);
  90 + if (res)
  91 + return res;
  92 +
  93 + slot = params[0].u.value.a;
  94 + if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
  95 + printf("Rollback index slot out of bounds %u\n", slot);
  96 + return TEE_ERROR_BAD_PARAMETERS;
  97 + }
  98 +
  99 + val = ta_avb_rollback_indexes[slot];
  100 + params[1].u.value.a = val >> 32;
  101 + params[1].u.value.b = val;
  102 + return TEE_SUCCESS;
  103 +
  104 + case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
  105 + res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
  106 + TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
  107 + TEE_PARAM_ATTR_TYPE_NONE,
  108 + TEE_PARAM_ATTR_TYPE_NONE,
  109 + num_params, params);
  110 + if (res)
  111 + return res;
  112 +
  113 + slot = params[0].u.value.a;
  114 + if (slot >= ARRAY_SIZE(ta_avb_rollback_indexes)) {
  115 + printf("Rollback index slot out of bounds %u\n", slot);
  116 + return TEE_ERROR_BAD_PARAMETERS;
  117 + }
  118 +
  119 + val = (u64)params[1].u.value.a << 32 | params[1].u.value.b;
  120 + if (val < ta_avb_rollback_indexes[slot])
  121 + return TEE_ERROR_SECURITY;
  122 +
  123 + ta_avb_rollback_indexes[slot] = val;
  124 + return TEE_SUCCESS;
  125 +
  126 + case TA_AVB_CMD_READ_LOCK_STATE:
  127 + res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
  128 + TEE_PARAM_ATTR_TYPE_NONE,
  129 + TEE_PARAM_ATTR_TYPE_NONE,
  130 + TEE_PARAM_ATTR_TYPE_NONE,
  131 + num_params, params);
  132 + if (res)
  133 + return res;
  134 +
  135 + params[0].u.value.a = ta_avb_lock_state;
  136 + return TEE_SUCCESS;
  137 +
  138 + case TA_AVB_CMD_WRITE_LOCK_STATE:
  139 + res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
  140 + TEE_PARAM_ATTR_TYPE_NONE,
  141 + TEE_PARAM_ATTR_TYPE_NONE,
  142 + TEE_PARAM_ATTR_TYPE_NONE,
  143 + num_params, params);
  144 + if (res)
  145 + return res;
  146 +
  147 + if (ta_avb_lock_state != params[0].u.value.a) {
  148 + ta_avb_lock_state = params[0].u.value.a;
  149 + memset(ta_avb_rollback_indexes, 0,
  150 + sizeof(ta_avb_rollback_indexes));
  151 + }
  152 +
  153 + return TEE_SUCCESS;
  154 +
  155 + default:
  156 + return TEE_ERROR_NOT_SUPPORTED;
  157 + }
  158 +}
  159 +#endif /*OPTEE_TA_AVB*/
  160 +
  161 +static const struct ta_entry ta_entries[] = {
  162 +#ifdef CONFIG_OPTEE_TA_AVB
  163 + { .uuid = TA_AVB_UUID,
  164 + .open_session = ta_avb_open_session,
  165 + .invoke_func = ta_avb_invoke_func,
  166 + },
  167 +#endif
  168 +};
  169 +
  170 +static void sandbox_tee_get_version(struct udevice *dev,
  171 + struct tee_version_data *vers)
  172 +{
  173 + struct tee_version_data v = {
  174 + .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
  175 + };
  176 +
  177 + *vers = v;
  178 +}
  179 +
  180 +static int sandbox_tee_close_session(struct udevice *dev, u32 session)
  181 +{
  182 + struct sandbox_tee_state *state = dev_get_priv(dev);
  183 +
  184 + if (!state->ta || state->session != session)
  185 + return -EINVAL;
  186 +
  187 + state->session = 0;
  188 + state->ta = NULL;
  189 +
  190 + return 0;
  191 +}
  192 +
  193 +static const struct ta_entry *find_ta_entry(u8 uuid[TEE_UUID_LEN])
  194 +{
  195 + struct tee_optee_ta_uuid u;
  196 + uint n;
  197 +
  198 + tee_optee_ta_uuid_from_octets(&u, uuid);
  199 +
  200 + for (n = 0; n < ARRAY_SIZE(ta_entries); n++)
  201 + if (!memcmp(&u, &ta_entries[n].uuid, sizeof(u)))
  202 + return ta_entries + n;
  203 +
  204 + return NULL;
  205 +}
  206 +
  207 +static int sandbox_tee_open_session(struct udevice *dev,
  208 + struct tee_open_session_arg *arg,
  209 + uint num_params, struct tee_param *params)
  210 +{
  211 + struct sandbox_tee_state *state = dev_get_priv(dev);
  212 + const struct ta_entry *ta;
  213 +
  214 + if (state->ta) {
  215 + printf("A session is already open\n");
  216 + return -EBUSY;
  217 + }
  218 +
  219 + ta = find_ta_entry(arg->uuid);
  220 + if (!ta) {
  221 + printf("Cannot find TA\n");
  222 + arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
  223 + arg->ret_origin = TEE_ORIGIN_TEE;
  224 +
  225 + return 0;
  226 + }
  227 +
  228 + arg->ret = ta->open_session(num_params, params);
  229 + arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
  230 +
  231 + if (!arg->ret) {
  232 + state->ta = (void *)ta;
  233 + state->session = 1;
  234 + arg->session = state->session;
  235 + } else {
  236 + printf("Cannot open session, TA returns error\n");
  237 + }
  238 +
  239 + return 0;
  240 +}
  241 +
  242 +static int sandbox_tee_invoke_func(struct udevice *dev,
  243 + struct tee_invoke_arg *arg,
  244 + uint num_params, struct tee_param *params)
  245 +{
  246 + struct sandbox_tee_state *state = dev_get_priv(dev);
  247 + struct ta_entry *ta = state->ta;
  248 +
  249 + if (!arg->session) {
  250 + printf("Missing session\n");
  251 + return -EINVAL;
  252 + }
  253 +
  254 + if (!ta) {
  255 + printf("TA session not available\n");
  256 + return -EINVAL;
  257 + }
  258 +
  259 + if (arg->session != state->session) {
  260 + printf("Session mismatch\n");
  261 + return -EINVAL;
  262 + }
  263 +
  264 + arg->ret = ta->invoke_func(arg->func, num_params, params);
  265 + arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
  266 +
  267 + return 0;
  268 +}
  269 +
  270 +static int sandbox_tee_shm_register(struct udevice *dev, struct tee_shm *shm)
  271 +{
  272 + struct sandbox_tee_state *state = dev_get_priv(dev);
  273 +
  274 + state->num_shms++;
  275 +
  276 + return 0;
  277 +}
  278 +
  279 +static int sandbox_tee_shm_unregister(struct udevice *dev, struct tee_shm *shm)
  280 +{
  281 + struct sandbox_tee_state *state = dev_get_priv(dev);
  282 +
  283 + state->num_shms--;
  284 +
  285 + return 0;
  286 +}
  287 +
  288 +static const struct tee_driver_ops sandbox_tee_ops = {
  289 + .get_version = sandbox_tee_get_version,
  290 + .open_session = sandbox_tee_open_session,
  291 + .close_session = sandbox_tee_close_session,
  292 + .invoke_func = sandbox_tee_invoke_func,
  293 + .shm_register = sandbox_tee_shm_register,
  294 + .shm_unregister = sandbox_tee_shm_unregister,
  295 +};
  296 +
  297 +static const struct udevice_id sandbox_tee_match[] = {
  298 + { .compatible = "sandbox,tee" },
  299 + {},
  300 +};
  301 +
  302 +U_BOOT_DRIVER(sandbox_tee) = {
  303 + .name = "sandbox_tee",
  304 + .id = UCLASS_TEE,
  305 + .of_match = sandbox_tee_match,
  306 + .ops = &sandbox_tee_ops,
  307 + .priv_auto_alloc_size = sizeof(struct sandbox_tee_state),
  308 +};
include/sandboxtee.h
  1 +/* SPDX-License-Identifier: GPL-2.0+ */
  2 +/*
  3 + * Copyright (C) 2018 Linaro Limited
  4 + */
  5 +
  6 +#ifndef __SANDBOXTEE_H
  7 +#define __SANDBOXTEE_H
  8 +
  9 +/**
  10 + * struct sandbox_tee_state - internal state of the sandbox TEE
  11 + * @session: current open session
  12 + * @num_shms: number of registered shared memory objects
  13 + * @ta: Trusted Application of current session
  14 + */
  15 +struct sandbox_tee_state {
  16 + u32 session;
  17 + int num_shms;
  18 + void *ta;
  19 +};
  20 +
  21 +#endif /*__SANDBOXTEE_H*/