1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2018-2020, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <compiler.h> 8 #include <pkcs11_ta.h> 9 #include <tee_internal_api.h> 10 #include <tee_internal_api_extensions.h> 11 #include <util.h> 12 13 #include "pkcs11_helpers.h" 14 #include "pkcs11_token.h" 15 16 TEE_Result TA_CreateEntryPoint(void) 17 { 18 return pkcs11_init(); 19 } 20 21 void TA_DestroyEntryPoint(void) 22 { 23 pkcs11_deinit(); 24 } 25 26 TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types, 27 TEE_Param __unused params[4], 28 void **tee_session) 29 { 30 struct pkcs11_client *client = register_client(); 31 32 if (!client) 33 return TEE_ERROR_OUT_OF_MEMORY; 34 35 *tee_session = client; 36 37 return TEE_SUCCESS; 38 } 39 40 void TA_CloseSessionEntryPoint(void *tee_session) 41 { 42 struct pkcs11_client *client = tee_session2client(tee_session); 43 44 unregister_client(client); 45 } 46 47 /* 48 * Entry point for invocation command PKCS11_CMD_PING 49 * 50 * Return a PKCS11_CKR_* value which is also loaded into the output param#0 51 */ 52 static uint32_t entry_ping(uint32_t ptypes, TEE_Param *params) 53 { 54 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 55 TEE_PARAM_TYPE_NONE, 56 TEE_PARAM_TYPE_MEMREF_OUTPUT, 57 TEE_PARAM_TYPE_NONE); 58 TEE_Param *out = ¶ms[2]; 59 const uint32_t ver[] = { 60 PKCS11_TA_VERSION_MAJOR, 61 PKCS11_TA_VERSION_MINOR, 62 PKCS11_TA_VERSION_PATCH, 63 }; 64 65 if (ptypes != exp_pt || 66 params[0].memref.size != TEE_PARAM0_SIZE_MIN || 67 out->memref.size != sizeof(ver)) 68 return PKCS11_CKR_ARGUMENTS_BAD; 69 70 TEE_MemMove(out->memref.buffer, ver, sizeof(ver)); 71 72 return PKCS11_CKR_OK; 73 } 74 75 static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index) 76 { 77 return TEE_PARAM_TYPE_GET(ptypes, index) == 78 TEE_PARAM_TYPE_NONE; 79 } 80 81 static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index) 82 { 83 switch (TEE_PARAM_TYPE_GET(ptypes, index)) { 84 case TEE_PARAM_TYPE_MEMREF_INPUT: 85 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 86 case TEE_PARAM_TYPE_MEMREF_INOUT: 87 return true; 88 default: 89 return false; 90 } 91 } 92 93 static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index) 94 { 95 return TEE_PARAM_TYPE_GET(ptypes, index) == 96 TEE_PARAM_TYPE_MEMREF_INPUT; 97 } 98 99 static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index) 100 { 101 return TEE_PARAM_TYPE_GET(ptypes, index) == 102 TEE_PARAM_TYPE_MEMREF_OUTPUT; 103 } 104 105 /* 106 * Entry point for PKCS11 TA commands 107 * 108 * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized 109 * arguments for the invoked command while the output data is used to send 110 * back to the client a PKCS11 finer status ID than the GPD TEE result codes 111 * Client shall check the status ID from the parameter #0 output buffer together 112 * with the GPD TEE result code. 113 */ 114 TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd, 115 uint32_t ptypes, 116 TEE_Param params[TEE_NUM_PARAMS]) 117 { 118 struct pkcs11_client *client = tee_session2client(tee_session); 119 uint32_t rc = 0; 120 121 if (!client) 122 return TEE_ERROR_SECURITY; 123 124 /* All command handlers will check only against 4 parameters */ 125 COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4); 126 127 /* 128 * Param#0 must be either an output or an inout memref as used to 129 * store the output return value for the invoked command. 130 */ 131 switch (TEE_PARAM_TYPE_GET(ptypes, 0)) { 132 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 133 case TEE_PARAM_TYPE_MEMREF_INOUT: 134 if (params[0].memref.size < sizeof(rc)) 135 return TEE_ERROR_BAD_PARAMETERS; 136 break; 137 default: 138 return TEE_ERROR_BAD_PARAMETERS; 139 } 140 141 DMSG("%s p#0 %"PRIu32"@%p, p#1 %s %"PRIu32"@%p, p#2 %s %"PRIu32"@%p", 142 id2str_ta_cmd(cmd), 143 params[0].memref.size, params[0].memref.buffer, 144 param_is_input(ptypes, 1) ? "in" : 145 param_is_output(ptypes, 1) ? "out" : "---", 146 param_is_memref(ptypes, 1) ? params[1].memref.size : 0, 147 param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL, 148 param_is_input(ptypes, 2) ? "in" : 149 param_is_output(ptypes, 2) ? "out" : "---", 150 param_is_memref(ptypes, 2) ? params[2].memref.size : 0, 151 param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL); 152 153 switch (cmd) { 154 case PKCS11_CMD_PING: 155 rc = entry_ping(ptypes, params); 156 break; 157 158 case PKCS11_CMD_SLOT_LIST: 159 rc = entry_ck_slot_list(ptypes, params); 160 break; 161 case PKCS11_CMD_SLOT_INFO: 162 rc = entry_ck_slot_info(ptypes, params); 163 break; 164 case PKCS11_CMD_TOKEN_INFO: 165 rc = entry_ck_token_info(ptypes, params); 166 break; 167 case PKCS11_CMD_MECHANISM_IDS: 168 rc = entry_ck_token_mecha_ids(ptypes, params); 169 break; 170 case PKCS11_CMD_MECHANISM_INFO: 171 rc = entry_ck_token_mecha_info(ptypes, params); 172 break; 173 174 case PKCS11_CMD_OPEN_SESSION: 175 rc = entry_ck_open_session(client, ptypes, params); 176 break; 177 case PKCS11_CMD_CLOSE_SESSION: 178 rc = entry_ck_close_session(client, ptypes, params); 179 break; 180 case PKCS11_CMD_CLOSE_ALL_SESSIONS: 181 rc = entry_ck_close_all_sessions(client, ptypes, params); 182 break; 183 case PKCS11_CMD_SESSION_INFO: 184 rc = entry_ck_session_info(client, ptypes, params); 185 break; 186 187 default: 188 EMSG("Command 0x%"PRIx32" is not supported", cmd); 189 return TEE_ERROR_NOT_SUPPORTED; 190 } 191 192 DMSG("%s rc 0x%08"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc)); 193 194 TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc)); 195 params[0].memref.size = sizeof(rc); 196 197 if (rc == PKCS11_CKR_BUFFER_TOO_SMALL) 198 return TEE_ERROR_SHORT_BUFFER; 199 else 200 return TEE_SUCCESS; 201 } 202