1*b0e1c5e4SJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-2-Clause
2*b0e1c5e4SJorge Ramirez-Ortiz /*
3*b0e1c5e4SJorge Ramirez-Ortiz * Copyright (C) Foundries Ltd. 2021 - All Rights Reserved
4*b0e1c5e4SJorge Ramirez-Ortiz * Author: Jorge Ramirez <jorge@foundries.io>
5*b0e1c5e4SJorge Ramirez-Ortiz */
6*b0e1c5e4SJorge Ramirez-Ortiz #include <crypto/crypto_se.h>
7*b0e1c5e4SJorge Ramirez-Ortiz #include <kernel/pseudo_ta.h>
8*b0e1c5e4SJorge Ramirez-Ortiz #include <pta_apdu.h>
9*b0e1c5e4SJorge Ramirez-Ortiz
10*b0e1c5e4SJorge Ramirez-Ortiz #define PTA_NAME "pta.apdu"
11*b0e1c5e4SJorge Ramirez-Ortiz
get_apdu_type(uint32_t val,enum crypto_apdu_type * type)12*b0e1c5e4SJorge Ramirez-Ortiz static TEE_Result get_apdu_type(uint32_t val, enum crypto_apdu_type *type)
13*b0e1c5e4SJorge Ramirez-Ortiz {
14*b0e1c5e4SJorge Ramirez-Ortiz switch (val) {
15*b0e1c5e4SJorge Ramirez-Ortiz case PTA_APDU_TXRX_CASE_NO_HINT:
16*b0e1c5e4SJorge Ramirez-Ortiz *type = CRYPTO_APDU_CASE_NO_HINT;
17*b0e1c5e4SJorge Ramirez-Ortiz break;
18*b0e1c5e4SJorge Ramirez-Ortiz case PTA_APDU_TXRX_CASE_1:
19*b0e1c5e4SJorge Ramirez-Ortiz *type = CRYPTO_APDU_CASE_1;
20*b0e1c5e4SJorge Ramirez-Ortiz break;
21*b0e1c5e4SJorge Ramirez-Ortiz case PTA_APDU_TXRX_CASE_2:
22*b0e1c5e4SJorge Ramirez-Ortiz *type = CRYPTO_APDU_CASE_2;
23*b0e1c5e4SJorge Ramirez-Ortiz break;
24*b0e1c5e4SJorge Ramirez-Ortiz case PTA_APDU_TXRX_CASE_2E:
25*b0e1c5e4SJorge Ramirez-Ortiz *type = CRYPTO_APDU_CASE_2E;
26*b0e1c5e4SJorge Ramirez-Ortiz break;
27*b0e1c5e4SJorge Ramirez-Ortiz case PTA_APDU_TXRX_CASE_3:
28*b0e1c5e4SJorge Ramirez-Ortiz *type = CRYPTO_APDU_CASE_3;
29*b0e1c5e4SJorge Ramirez-Ortiz break;
30*b0e1c5e4SJorge Ramirez-Ortiz case PTA_APDU_TXRX_CASE_3E:
31*b0e1c5e4SJorge Ramirez-Ortiz *type = CRYPTO_APDU_CASE_3E;
32*b0e1c5e4SJorge Ramirez-Ortiz break;
33*b0e1c5e4SJorge Ramirez-Ortiz case PTA_APDU_TXRX_CASE_4:
34*b0e1c5e4SJorge Ramirez-Ortiz *type = CRYPTO_APDU_CASE_4;
35*b0e1c5e4SJorge Ramirez-Ortiz break;
36*b0e1c5e4SJorge Ramirez-Ortiz case PTA_APDU_TXRX_CASE_4E:
37*b0e1c5e4SJorge Ramirez-Ortiz *type = CRYPTO_APDU_CASE_4E;
38*b0e1c5e4SJorge Ramirez-Ortiz break;
39*b0e1c5e4SJorge Ramirez-Ortiz default:
40*b0e1c5e4SJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS;
41*b0e1c5e4SJorge Ramirez-Ortiz }
42*b0e1c5e4SJorge Ramirez-Ortiz return TEE_SUCCESS;
43*b0e1c5e4SJorge Ramirez-Ortiz }
44*b0e1c5e4SJorge Ramirez-Ortiz
invoke_command(void * session_context __unused,uint32_t command_id,uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])45*b0e1c5e4SJorge Ramirez-Ortiz static TEE_Result invoke_command(void *session_context __unused,
46*b0e1c5e4SJorge Ramirez-Ortiz uint32_t command_id, uint32_t pt,
47*b0e1c5e4SJorge Ramirez-Ortiz TEE_Param params[TEE_NUM_PARAMS])
48*b0e1c5e4SJorge Ramirez-Ortiz {
49*b0e1c5e4SJorge Ramirez-Ortiz const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
50*b0e1c5e4SJorge Ramirez-Ortiz TEE_PARAM_TYPE_MEMREF_INPUT,
51*b0e1c5e4SJorge Ramirez-Ortiz TEE_PARAM_TYPE_MEMREF_INPUT,
52*b0e1c5e4SJorge Ramirez-Ortiz TEE_PARAM_TYPE_MEMREF_OUTPUT);
53*b0e1c5e4SJorge Ramirez-Ortiz enum crypto_apdu_type type = CRYPTO_APDU_CASE_NO_HINT;
54*b0e1c5e4SJorge Ramirez-Ortiz TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
55*b0e1c5e4SJorge Ramirez-Ortiz size_t len = 0;
56*b0e1c5e4SJorge Ramirez-Ortiz
57*b0e1c5e4SJorge Ramirez-Ortiz FMSG("command entry point for pseudo-TA \"%s\"", PTA_NAME);
58*b0e1c5e4SJorge Ramirez-Ortiz
59*b0e1c5e4SJorge Ramirez-Ortiz if (pt != exp_pt)
60*b0e1c5e4SJorge Ramirez-Ortiz return TEE_ERROR_BAD_PARAMETERS;
61*b0e1c5e4SJorge Ramirez-Ortiz
62*b0e1c5e4SJorge Ramirez-Ortiz switch (command_id) {
63*b0e1c5e4SJorge Ramirez-Ortiz case PTA_CMD_TXRX_APDU_RAW_FRAME:
64*b0e1c5e4SJorge Ramirez-Ortiz ret = get_apdu_type(params[0].value.a, &type);
65*b0e1c5e4SJorge Ramirez-Ortiz if (ret)
66*b0e1c5e4SJorge Ramirez-Ortiz return ret;
67*b0e1c5e4SJorge Ramirez-Ortiz
68*b0e1c5e4SJorge Ramirez-Ortiz len = params[3].memref.size;
69*b0e1c5e4SJorge Ramirez-Ortiz ret = crypto_se_do_apdu(type,
70*b0e1c5e4SJorge Ramirez-Ortiz params[1].memref.buffer,
71*b0e1c5e4SJorge Ramirez-Ortiz params[1].memref.size,
72*b0e1c5e4SJorge Ramirez-Ortiz params[2].memref.buffer,
73*b0e1c5e4SJorge Ramirez-Ortiz params[2].memref.size,
74*b0e1c5e4SJorge Ramirez-Ortiz params[3].memref.buffer,
75*b0e1c5e4SJorge Ramirez-Ortiz &len);
76*b0e1c5e4SJorge Ramirez-Ortiz if (!ret)
77*b0e1c5e4SJorge Ramirez-Ortiz params[3].memref.size = len;
78*b0e1c5e4SJorge Ramirez-Ortiz break;
79*b0e1c5e4SJorge Ramirez-Ortiz default:
80*b0e1c5e4SJorge Ramirez-Ortiz return TEE_ERROR_NOT_IMPLEMENTED;
81*b0e1c5e4SJorge Ramirez-Ortiz }
82*b0e1c5e4SJorge Ramirez-Ortiz
83*b0e1c5e4SJorge Ramirez-Ortiz return ret;
84*b0e1c5e4SJorge Ramirez-Ortiz }
85*b0e1c5e4SJorge Ramirez-Ortiz
86*b0e1c5e4SJorge Ramirez-Ortiz pseudo_ta_register(.uuid = PTA_APDU_UUID, .name = PTA_NAME,
87*b0e1c5e4SJorge Ramirez-Ortiz .flags = PTA_DEFAULT_FLAGS,
88*b0e1c5e4SJorge Ramirez-Ortiz .invoke_command_entry_point = invoke_command);
89