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