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 **session) 29 { 30 *session = NULL; 31 32 return TEE_SUCCESS; 33 } 34 35 void TA_CloseSessionEntryPoint(void *session __unused) 36 { 37 } 38 39 /* 40 * Entry point for invocation command PKCS11_CMD_PING 41 * 42 * Return a PKCS11_CKR_* value which is also loaded into the output param#0 43 */ 44 static uint32_t entry_ping(uint32_t ptypes, TEE_Param *params) 45 { 46 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 47 TEE_PARAM_TYPE_NONE, 48 TEE_PARAM_TYPE_MEMREF_OUTPUT, 49 TEE_PARAM_TYPE_NONE); 50 TEE_Param *out = ¶ms[2]; 51 const uint32_t ver[] = { 52 PKCS11_TA_VERSION_MAJOR, 53 PKCS11_TA_VERSION_MINOR, 54 PKCS11_TA_VERSION_PATCH, 55 }; 56 57 if (ptypes != exp_pt || 58 params[0].memref.size != TEE_PARAM0_SIZE_MIN || 59 out->memref.size != sizeof(ver)) 60 return PKCS11_CKR_ARGUMENTS_BAD; 61 62 TEE_MemMove(out->memref.buffer, ver, sizeof(ver)); 63 64 return PKCS11_CKR_OK; 65 } 66 67 static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index) 68 { 69 return TEE_PARAM_TYPE_GET(ptypes, index) == 70 TEE_PARAM_TYPE_NONE; 71 } 72 73 static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index) 74 { 75 switch (TEE_PARAM_TYPE_GET(ptypes, index)) { 76 case TEE_PARAM_TYPE_MEMREF_INPUT: 77 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 78 case TEE_PARAM_TYPE_MEMREF_INOUT: 79 return true; 80 default: 81 return false; 82 } 83 } 84 85 static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index) 86 { 87 return TEE_PARAM_TYPE_GET(ptypes, index) == 88 TEE_PARAM_TYPE_MEMREF_INPUT; 89 } 90 91 static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index) 92 { 93 return TEE_PARAM_TYPE_GET(ptypes, index) == 94 TEE_PARAM_TYPE_MEMREF_OUTPUT; 95 } 96 97 /* 98 * Entry point for PKCS11 TA commands 99 * 100 * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized 101 * arguments for the invoked command while the output data is used to send 102 * back to the client a PKCS11 finer status ID than the GPD TEE result codes 103 * Client shall check the status ID from the parameter #0 output buffer together 104 * with the GPD TEE result code. 105 */ 106 TEE_Result TA_InvokeCommandEntryPoint(void *tee_session __unused, uint32_t cmd, 107 uint32_t ptypes, 108 TEE_Param params[TEE_NUM_PARAMS]) 109 { 110 uint32_t rc = 0; 111 112 /* All command handlers will check only against 4 parameters */ 113 COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4); 114 115 /* 116 * Param#0 must be either an output or an inout memref as used to 117 * store the output return value for the invoked command. 118 */ 119 switch (TEE_PARAM_TYPE_GET(ptypes, 0)) { 120 case TEE_PARAM_TYPE_MEMREF_OUTPUT: 121 case TEE_PARAM_TYPE_MEMREF_INOUT: 122 if (params[0].memref.size < sizeof(rc)) 123 return TEE_ERROR_BAD_PARAMETERS; 124 break; 125 default: 126 return TEE_ERROR_BAD_PARAMETERS; 127 } 128 129 DMSG("%s p#0 %"PRIu32"@%p, p#1 %s %"PRIu32"@%p, p#2 %s %"PRIu32"@%p", 130 id2str_ta_cmd(cmd), 131 params[0].memref.size, params[0].memref.buffer, 132 param_is_input(ptypes, 1) ? "in" : 133 param_is_output(ptypes, 1) ? "out" : "---", 134 param_is_memref(ptypes, 1) ? params[1].memref.size : 0, 135 param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL, 136 param_is_input(ptypes, 2) ? "in" : 137 param_is_output(ptypes, 2) ? "out" : "---", 138 param_is_memref(ptypes, 2) ? params[2].memref.size : 0, 139 param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL); 140 141 switch (cmd) { 142 case PKCS11_CMD_PING: 143 rc = entry_ping(ptypes, params); 144 break; 145 146 case PKCS11_CMD_SLOT_LIST: 147 rc = entry_ck_slot_list(ptypes, params); 148 break; 149 case PKCS11_CMD_SLOT_INFO: 150 rc = entry_ck_slot_info(ptypes, params); 151 break; 152 case PKCS11_CMD_TOKEN_INFO: 153 rc = entry_ck_token_info(ptypes, params); 154 break; 155 156 default: 157 EMSG("Command 0x%"PRIx32" is not supported", cmd); 158 return TEE_ERROR_NOT_SUPPORTED; 159 } 160 161 DMSG("%s rc 0x%08"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc)); 162 163 TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc)); 164 params[0].memref.size = sizeof(rc); 165 166 if (rc == PKCS11_CKR_BUFFER_TOO_SMALL) 167 return TEE_ERROR_SHORT_BUFFER; 168 else 169 return TEE_SUCCESS; 170 } 171