uboot/drivers/tee/sandbox.c
<<
>>
Prefs
   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#include <tee/optee_ta_rpc_test.h>
  11#include <tee/optee_ta_scp03.h>
  12
  13#include "optee/optee_msg.h"
  14#include "optee/optee_private.h"
  15
  16/*
  17 * The sandbox tee driver tries to emulate a generic Trusted Exectution
  18 * Environment (TEE) with the Trusted Applications (TA) OPTEE_TA_AVB and
  19 * OPTEE_TA_RPC_TEST available.
  20 */
  21
  22static const u32 pstorage_max = 16;
  23/**
  24 * struct ta_entry - TA entries
  25 * @uuid:               UUID of an emulated TA
  26 * @open_session        Called when a session is openened to the TA
  27 * @invoke_func         Called when a function in the TA is to be invoked
  28 *
  29 * This struct is used to register TAs in this sandbox emulation of a TEE.
  30 */
  31struct ta_entry {
  32        struct tee_optee_ta_uuid uuid;
  33        u32 (*open_session)(struct udevice *dev, uint num_params,
  34                            struct tee_param *params);
  35        u32 (*invoke_func)(struct udevice *dev,
  36                           u32 func, uint num_params,
  37                           struct tee_param *params);
  38};
  39
  40static int get_msg_arg(struct udevice *dev, uint num_params,
  41                       struct tee_shm **shmp, struct optee_msg_arg **msg_arg)
  42{
  43        int rc;
  44        struct optee_msg_arg *ma;
  45
  46        rc = __tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL,
  47                           OPTEE_MSG_GET_ARG_SIZE(num_params), TEE_SHM_ALLOC,
  48                           shmp);
  49        if (rc)
  50                return rc;
  51
  52        ma = (*shmp)->addr;
  53        memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
  54        ma->num_params = num_params;
  55        *msg_arg = ma;
  56
  57        return 0;
  58}
  59
  60void *optee_alloc_and_init_page_list(void *buf, ulong len,
  61                                     u64 *phys_buf_ptr)
  62{
  63        /*
  64         * An empty stub is added just to fix linking issues.
  65         * This function isn't supposed to be called in sandbox
  66         * setup, otherwise replace this with a proper
  67         * implementation from optee/core.c
  68         */
  69        return NULL;
  70}
  71
  72#if defined(CONFIG_OPTEE_TA_SCP03) || defined(CONFIG_OPTEE_TA_AVB)
  73static u32 get_attr(uint n, uint num_params, struct tee_param *params)
  74{
  75        if (n >= num_params)
  76                return TEE_PARAM_ATTR_TYPE_NONE;
  77
  78        return params[n].attr;
  79}
  80
  81static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params,
  82                        struct tee_param *params)
  83{
  84        u8 p[] = { p0, p1, p2, p3 };
  85        uint n;
  86
  87        for (n = 0; n < ARRAY_SIZE(p); n++)
  88                if (p[n] != get_attr(n, num_params, params))
  89                        goto bad_params;
  90
  91        for (; n < num_params; n++)
  92                if (get_attr(n, num_params, params))
  93                        goto bad_params;
  94
  95        return TEE_SUCCESS;
  96
  97bad_params:
  98        printf("Bad param attrs\n");
  99
 100        return TEE_ERROR_BAD_PARAMETERS;
 101}
 102#endif
 103
 104#ifdef CONFIG_OPTEE_TA_SCP03
 105static u32 pta_scp03_open_session(struct udevice *dev, uint num_params,
 106                                  struct tee_param *params)
 107{
 108        /*
 109         * We don't expect additional parameters when opening a session to
 110         * this TA.
 111         */
 112        return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
 113                            TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
 114                            num_params, params);
 115}
 116
 117static u32 pta_scp03_invoke_func(struct udevice *dev, u32 func, uint num_params,
 118                                 struct tee_param *params)
 119{
 120        u32 res;
 121        static bool enabled;
 122
 123        switch (func) {
 124        case PTA_CMD_ENABLE_SCP03:
 125                res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
 126                                   TEE_PARAM_ATTR_TYPE_NONE,
 127                                   TEE_PARAM_ATTR_TYPE_NONE,
 128                                   TEE_PARAM_ATTR_TYPE_NONE,
 129                                   num_params, params);
 130                if (res)
 131                        return res;
 132
 133                if (!enabled) {
 134                        enabled = true;
 135                } else {
 136                }
 137
 138                if (params[0].u.value.a)
 139
 140                return TEE_SUCCESS;
 141        default:
 142                return TEE_ERROR_NOT_SUPPORTED;
 143        }
 144}
 145#endif
 146
 147#ifdef CONFIG_OPTEE_TA_AVB
 148static u32 ta_avb_open_session(struct udevice *dev, uint num_params,
 149                               struct tee_param *params)
 150{
 151        /*
 152         * We don't expect additional parameters when opening a session to
 153         * this TA.
 154         */
 155        return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
 156                            TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
 157                            num_params, params);
 158}
 159
 160static u32 ta_avb_invoke_func(struct udevice *dev, u32 func, uint num_params,
 161                              struct tee_param *params)
 162{
 163        struct sandbox_tee_state *state = dev_get_priv(dev);
 164        struct env_entry e, *ep;
 165        char *name;
 166        u32 res;
 167        uint slot;
 168        u64 val;
 169        char *value;
 170        u32 value_sz;
 171
 172        switch (func) {
 173        case TA_AVB_CMD_READ_ROLLBACK_INDEX:
 174                res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
 175                                   TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
 176                                   TEE_PARAM_ATTR_TYPE_NONE,
 177                                   TEE_PARAM_ATTR_TYPE_NONE,
 178                                   num_params, params);
 179                if (res)
 180                        return res;
 181
 182                slot = params[0].u.value.a;
 183                if (slot >= ARRAY_SIZE(state->ta_avb_rollback_indexes)) {
 184                        printf("Rollback index slot out of bounds %u\n", slot);
 185                        return TEE_ERROR_BAD_PARAMETERS;
 186                }
 187
 188                val = state->ta_avb_rollback_indexes[slot];
 189                params[1].u.value.a = val >> 32;
 190                params[1].u.value.b = val;
 191                return TEE_SUCCESS;
 192
 193        case TA_AVB_CMD_WRITE_ROLLBACK_INDEX:
 194                res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
 195                                   TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
 196                                   TEE_PARAM_ATTR_TYPE_NONE,
 197                                   TEE_PARAM_ATTR_TYPE_NONE,
 198                                   num_params, params);
 199                if (res)
 200                        return res;
 201
 202                slot = params[0].u.value.a;
 203                if (slot >= ARRAY_SIZE(state->ta_avb_rollback_indexes)) {
 204                        printf("Rollback index slot out of bounds %u\n", slot);
 205                        return TEE_ERROR_BAD_PARAMETERS;
 206                }
 207
 208                val = (u64)params[1].u.value.a << 32 | params[1].u.value.b;
 209                if (val < state->ta_avb_rollback_indexes[slot])
 210                        return TEE_ERROR_SECURITY;
 211
 212                state->ta_avb_rollback_indexes[slot] = val;
 213                return TEE_SUCCESS;
 214
 215        case TA_AVB_CMD_READ_LOCK_STATE:
 216                res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT,
 217                                   TEE_PARAM_ATTR_TYPE_NONE,
 218                                   TEE_PARAM_ATTR_TYPE_NONE,
 219                                   TEE_PARAM_ATTR_TYPE_NONE,
 220                                   num_params, params);
 221                if (res)
 222                        return res;
 223
 224                params[0].u.value.a = state->ta_avb_lock_state;
 225                return TEE_SUCCESS;
 226
 227        case TA_AVB_CMD_WRITE_LOCK_STATE:
 228                res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
 229                                   TEE_PARAM_ATTR_TYPE_NONE,
 230                                   TEE_PARAM_ATTR_TYPE_NONE,
 231                                   TEE_PARAM_ATTR_TYPE_NONE,
 232                                   num_params, params);
 233                if (res)
 234                        return res;
 235
 236                if (state->ta_avb_lock_state != params[0].u.value.a) {
 237                        state->ta_avb_lock_state = params[0].u.value.a;
 238                        memset(state->ta_avb_rollback_indexes, 0,
 239                               sizeof(state->ta_avb_rollback_indexes));
 240                }
 241
 242                return TEE_SUCCESS;
 243        case TA_AVB_CMD_READ_PERSIST_VALUE:
 244                res = check_params(TEE_PARAM_ATTR_TYPE_MEMREF_INPUT,
 245                                   TEE_PARAM_ATTR_TYPE_MEMREF_INOUT,
 246                                   TEE_PARAM_ATTR_TYPE_NONE,
 247                                   TEE_PARAM_ATTR_TYPE_NONE,
 248                                   num_params, params);
 249                if (res)
 250                        return res;
 251
 252                name = params[0].u.memref.shm->addr;
 253
 254                value = params[1].u.memref.shm->addr;
 255                value_sz = params[1].u.memref.size;
 256
 257                e.key = name;
 258                e.data = NULL;
 259                hsearch_r(e, ENV_FIND, &ep, &state->pstorage_htab, 0);
 260                if (!ep)
 261                        return TEE_ERROR_ITEM_NOT_FOUND;
 262
 263                value_sz = strlen(ep->data) + 1;
 264                memcpy(value, ep->data, value_sz);
 265
 266                return TEE_SUCCESS;
 267        case TA_AVB_CMD_WRITE_PERSIST_VALUE:
 268                res = check_params(TEE_PARAM_ATTR_TYPE_MEMREF_INPUT,
 269                                   TEE_PARAM_ATTR_TYPE_MEMREF_INPUT,
 270                                   TEE_PARAM_ATTR_TYPE_NONE,
 271                                   TEE_PARAM_ATTR_TYPE_NONE,
 272                                   num_params, params);
 273                if (res)
 274                        return res;
 275
 276                name = params[0].u.memref.shm->addr;
 277
 278                value = params[1].u.memref.shm->addr;
 279                value_sz = params[1].u.memref.size;
 280
 281                e.key = name;
 282                e.data = NULL;
 283                hsearch_r(e, ENV_FIND, &ep, &state->pstorage_htab, 0);
 284                if (ep)
 285                        hdelete_r(e.key, &state->pstorage_htab, 0);
 286
 287                e.key = name;
 288                e.data = value;
 289                hsearch_r(e, ENV_ENTER, &ep, &state->pstorage_htab, 0);
 290                if (!ep)
 291                        return TEE_ERROR_OUT_OF_MEMORY;
 292
 293                return TEE_SUCCESS;
 294
 295        default:
 296                return TEE_ERROR_NOT_SUPPORTED;
 297        }
 298}
 299#endif /* OPTEE_TA_AVB */
 300
 301#ifdef CONFIG_OPTEE_TA_RPC_TEST
 302static u32 ta_rpc_test_open_session(struct udevice *dev, uint num_params,
 303                                    struct tee_param *params)
 304{
 305        /*
 306         * We don't expect additional parameters when opening a session to
 307         * this TA.
 308         */
 309        return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
 310                            TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE,
 311                            num_params, params);
 312}
 313
 314static void fill_i2c_rpc_params(struct optee_msg_arg *msg_arg, u64 bus_num,
 315                                u64 chip_addr, u64 xfer_flags, u64 op,
 316                                struct tee_param_memref memref)
 317{
 318        msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
 319        msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
 320        msg_arg->params[2].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INOUT;
 321        msg_arg->params[3].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
 322
 323        /* trigger I2C services of TEE supplicant */
 324        msg_arg->cmd = OPTEE_MSG_RPC_CMD_I2C_TRANSFER;
 325
 326        msg_arg->params[0].u.value.a = op;
 327        msg_arg->params[0].u.value.b = bus_num;
 328        msg_arg->params[0].u.value.c = chip_addr;
 329        msg_arg->params[1].u.value.a = xfer_flags;
 330
 331        /* buffer to read/write data */
 332        msg_arg->params[2].u.rmem.shm_ref = (ulong)memref.shm;
 333        msg_arg->params[2].u.rmem.size = memref.size;
 334        msg_arg->params[2].u.rmem.offs = memref.shm_offs;
 335
 336        msg_arg->num_params = 4;
 337}
 338
 339static u32 ta_rpc_test_invoke_func(struct udevice *dev, u32 func,
 340                                   uint num_params,
 341                                   struct tee_param *params)
 342{
 343        struct tee_shm *shm;
 344        struct tee_param_memref memref_data;
 345        struct optee_msg_arg *msg_arg;
 346        int chip_addr, bus_num, op, xfer_flags;
 347        int res;
 348
 349        res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT,
 350                           TEE_PARAM_ATTR_TYPE_MEMREF_INOUT,
 351                           TEE_PARAM_ATTR_TYPE_NONE,
 352                           TEE_PARAM_ATTR_TYPE_NONE,
 353                           num_params, params);
 354        if (res)
 355                return TEE_ERROR_BAD_PARAMETERS;
 356
 357        bus_num = params[0].u.value.a;
 358        chip_addr = params[0].u.value.b;
 359        xfer_flags = params[0].u.value.c;
 360        memref_data = params[1].u.memref;
 361
 362        switch (func) {
 363        case TA_RPC_TEST_CMD_I2C_READ:
 364                op = OPTEE_MSG_RPC_CMD_I2C_TRANSFER_RD;
 365                break;
 366        case TA_RPC_TEST_CMD_I2C_WRITE:
 367                op = OPTEE_MSG_RPC_CMD_I2C_TRANSFER_WR;
 368                break;
 369        default:
 370                return TEE_ERROR_NOT_SUPPORTED;
 371        }
 372
 373        /*
 374         * Fill params for an RPC call to tee supplicant
 375         */
 376        res = get_msg_arg(dev, 4, &shm, &msg_arg);
 377        if (res)
 378                goto out;
 379
 380        fill_i2c_rpc_params(msg_arg, bus_num, chip_addr, xfer_flags, op,
 381                            memref_data);
 382
 383        /* Make an RPC call to tee supplicant */
 384        optee_suppl_cmd(dev, shm, 0);
 385        res = msg_arg->ret;
 386out:
 387        tee_shm_free(shm);
 388
 389        return res;
 390}
 391#endif /* CONFIG_OPTEE_TA_RPC_TEST */
 392
 393static const struct ta_entry ta_entries[] = {
 394#ifdef CONFIG_OPTEE_TA_AVB
 395        { .uuid = TA_AVB_UUID,
 396          .open_session = ta_avb_open_session,
 397          .invoke_func = ta_avb_invoke_func,
 398        },
 399#endif
 400#ifdef CONFIG_OPTEE_TA_RPC_TEST
 401        { .uuid = TA_RPC_TEST_UUID,
 402          .open_session = ta_rpc_test_open_session,
 403          .invoke_func = ta_rpc_test_invoke_func,
 404        },
 405#endif
 406#ifdef CONFIG_OPTEE_TA_SCP03
 407        { .uuid = PTA_SCP03_UUID,
 408          .open_session = pta_scp03_open_session,
 409          .invoke_func = pta_scp03_invoke_func,
 410        },
 411#endif
 412};
 413
 414static void sandbox_tee_get_version(struct udevice *dev,
 415                                    struct tee_version_data *vers)
 416{
 417        struct tee_version_data v = {
 418                .gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
 419        };
 420
 421        *vers = v;
 422}
 423
 424static int sandbox_tee_close_session(struct udevice *dev, u32 session)
 425{
 426        struct sandbox_tee_state *state = dev_get_priv(dev);
 427
 428        if (!state->ta || state->session != session)
 429                return -EINVAL;
 430
 431        state->session = 0;
 432        state->ta = NULL;
 433
 434        return 0;
 435}
 436
 437static const struct ta_entry *find_ta_entry(u8 uuid[TEE_UUID_LEN])
 438{
 439        struct tee_optee_ta_uuid u;
 440        uint n;
 441
 442        tee_optee_ta_uuid_from_octets(&u, uuid);
 443
 444        for (n = 0; n < ARRAY_SIZE(ta_entries); n++)
 445                if (!memcmp(&u, &ta_entries[n].uuid, sizeof(u)))
 446                        return ta_entries + n;
 447
 448        return NULL;
 449}
 450
 451static int sandbox_tee_open_session(struct udevice *dev,
 452                                    struct tee_open_session_arg *arg,
 453                                    uint num_params, struct tee_param *params)
 454{
 455        struct sandbox_tee_state *state = dev_get_priv(dev);
 456        const struct ta_entry *ta;
 457
 458        if (state->ta) {
 459                printf("A session is already open\n");
 460                return -EBUSY;
 461        }
 462
 463        ta = find_ta_entry(arg->uuid);
 464        if (!ta) {
 465                printf("Cannot find TA\n");
 466                arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
 467                arg->ret_origin = TEE_ORIGIN_TEE;
 468
 469                return 0;
 470        }
 471
 472        arg->ret = ta->open_session(dev, num_params, params);
 473        arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
 474
 475        if (!arg->ret) {
 476                state->ta = (void *)ta;
 477                state->session = 1;
 478                arg->session = state->session;
 479        } else {
 480                printf("Cannot open session, TA returns error\n");
 481        }
 482
 483        return 0;
 484}
 485
 486static int sandbox_tee_invoke_func(struct udevice *dev,
 487                                   struct tee_invoke_arg *arg,
 488                                   uint num_params, struct tee_param *params)
 489{
 490        struct sandbox_tee_state *state = dev_get_priv(dev);
 491        struct ta_entry *ta = state->ta;
 492
 493        if (!arg->session) {
 494                printf("Missing session\n");
 495                return -EINVAL;
 496        }
 497
 498        if (!ta) {
 499                printf("TA session not available\n");
 500                return -EINVAL;
 501        }
 502
 503        if (arg->session != state->session) {
 504                printf("Session mismatch\n");
 505                return -EINVAL;
 506        }
 507
 508        arg->ret = ta->invoke_func(dev, arg->func, num_params, params);
 509        arg->ret_origin = TEE_ORIGIN_TRUSTED_APP;
 510
 511        return 0;
 512}
 513
 514static int sandbox_tee_shm_register(struct udevice *dev, struct tee_shm *shm)
 515{
 516        struct sandbox_tee_state *state = dev_get_priv(dev);
 517
 518        state->num_shms++;
 519
 520        return 0;
 521}
 522
 523static int sandbox_tee_shm_unregister(struct udevice *dev, struct tee_shm *shm)
 524{
 525        struct sandbox_tee_state *state = dev_get_priv(dev);
 526
 527        state->num_shms--;
 528
 529        return 0;
 530}
 531
 532static int sandbox_tee_remove(struct udevice *dev)
 533{
 534        struct sandbox_tee_state *state = dev_get_priv(dev);
 535
 536        hdestroy_r(&state->pstorage_htab);
 537
 538        return 0;
 539}
 540
 541static int sandbox_tee_probe(struct udevice *dev)
 542{
 543        struct sandbox_tee_state *state = dev_get_priv(dev);
 544        /*
 545         * With this hastable we emulate persistent storage,
 546         * which should contain persistent values
 547         * between different sessions/command invocations.
 548         */
 549        if (!hcreate_r(pstorage_max, &state->pstorage_htab))
 550                return TEE_ERROR_OUT_OF_MEMORY;
 551
 552        return 0;
 553}
 554
 555static const struct tee_driver_ops sandbox_tee_ops = {
 556        .get_version = sandbox_tee_get_version,
 557        .open_session = sandbox_tee_open_session,
 558        .close_session = sandbox_tee_close_session,
 559        .invoke_func = sandbox_tee_invoke_func,
 560        .shm_register = sandbox_tee_shm_register,
 561        .shm_unregister = sandbox_tee_shm_unregister,
 562};
 563
 564static const struct udevice_id sandbox_tee_match[] = {
 565        { .compatible = "sandbox,tee" },
 566        {},
 567};
 568
 569U_BOOT_DRIVER(sandbox_tee) = {
 570        .name = "sandbox_tee",
 571        .id = UCLASS_TEE,
 572        .of_match = sandbox_tee_match,
 573        .ops = &sandbox_tee_ops,
 574        .priv_auto      = sizeof(struct sandbox_tee_state),
 575        .probe = sandbox_tee_probe,
 576        .remove = sandbox_tee_remove,
 577};
 578