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