1f8a3a2c4SEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause 2f8a3a2c4SEtienne Carriere /* 3f8a3a2c4SEtienne Carriere * Copyright (c) 2018-2020, Linaro Limited 4f8a3a2c4SEtienne Carriere */ 5f8a3a2c4SEtienne Carriere 6208dec38SEtienne Carriere #include <assert.h> 7f8a3a2c4SEtienne Carriere #include <compiler.h> 86ea5aa6cSEtienne Carriere #include <pkcs11_ta.h> 9f8a3a2c4SEtienne Carriere #include <tee_internal_api.h> 1060290f69SEtienne Carriere #include <tee_internal_api_extensions.h> 11d34f3266SEtienne Carriere #include <util.h> 1260290f69SEtienne Carriere 1360290f69SEtienne Carriere #include "pkcs11_helpers.h" 14c84ccd0aSEtienne Carriere #include "pkcs11_token.h" 15f8a3a2c4SEtienne Carriere 16f8a3a2c4SEtienne Carriere TEE_Result TA_CreateEntryPoint(void) 17f8a3a2c4SEtienne Carriere { 18c84ccd0aSEtienne Carriere return pkcs11_init(); 19f8a3a2c4SEtienne Carriere } 20f8a3a2c4SEtienne Carriere 21f8a3a2c4SEtienne Carriere void TA_DestroyEntryPoint(void) 22f8a3a2c4SEtienne Carriere { 23c84ccd0aSEtienne Carriere pkcs11_deinit(); 24f8a3a2c4SEtienne Carriere } 25f8a3a2c4SEtienne Carriere 26f8a3a2c4SEtienne Carriere TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types, 27f8a3a2c4SEtienne Carriere TEE_Param __unused params[4], 28e084583eSEtienne Carriere void **tee_session) 29f8a3a2c4SEtienne Carriere { 30e084583eSEtienne Carriere struct pkcs11_client *client = register_client(); 31e084583eSEtienne Carriere 32e084583eSEtienne Carriere if (!client) 33e084583eSEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY; 34e084583eSEtienne Carriere 35e084583eSEtienne Carriere *tee_session = client; 36f8a3a2c4SEtienne Carriere 37f8a3a2c4SEtienne Carriere return TEE_SUCCESS; 38f8a3a2c4SEtienne Carriere } 39f8a3a2c4SEtienne Carriere 40e084583eSEtienne Carriere void TA_CloseSessionEntryPoint(void *tee_session) 41f8a3a2c4SEtienne Carriere { 42e084583eSEtienne Carriere struct pkcs11_client *client = tee_session2client(tee_session); 43e084583eSEtienne Carriere 44e084583eSEtienne Carriere unregister_client(client); 45f8a3a2c4SEtienne Carriere } 46f8a3a2c4SEtienne Carriere 47f8a3a2c4SEtienne Carriere /* 486ea5aa6cSEtienne Carriere * Entry point for invocation command PKCS11_CMD_PING 496ea5aa6cSEtienne Carriere * 50208dec38SEtienne Carriere * Return a PKCS11_CKR_* value which is also loaded into the output param#0 516ea5aa6cSEtienne Carriere */ 52208dec38SEtienne Carriere static uint32_t entry_ping(uint32_t ptypes, TEE_Param *params) 536ea5aa6cSEtienne Carriere { 54208dec38SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 55208dec38SEtienne Carriere TEE_PARAM_TYPE_NONE, 56208dec38SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 57208dec38SEtienne Carriere TEE_PARAM_TYPE_NONE); 58208dec38SEtienne Carriere TEE_Param *out = ¶ms[2]; 596ea5aa6cSEtienne Carriere const uint32_t ver[] = { 606ea5aa6cSEtienne Carriere PKCS11_TA_VERSION_MAJOR, 616ea5aa6cSEtienne Carriere PKCS11_TA_VERSION_MINOR, 626ea5aa6cSEtienne Carriere PKCS11_TA_VERSION_PATCH, 636ea5aa6cSEtienne Carriere }; 646ea5aa6cSEtienne Carriere 65208dec38SEtienne Carriere if (ptypes != exp_pt || 66208dec38SEtienne Carriere params[0].memref.size != TEE_PARAM0_SIZE_MIN || 67208dec38SEtienne Carriere out->memref.size != sizeof(ver)) 68208dec38SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 696ea5aa6cSEtienne Carriere 706ea5aa6cSEtienne Carriere TEE_MemMove(out->memref.buffer, ver, sizeof(ver)); 716ea5aa6cSEtienne Carriere 72d34f3266SEtienne Carriere return PKCS11_CKR_OK; 736ea5aa6cSEtienne Carriere } 746ea5aa6cSEtienne Carriere 75208dec38SEtienne Carriere static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index) 76208dec38SEtienne Carriere { 77208dec38SEtienne Carriere return TEE_PARAM_TYPE_GET(ptypes, index) == 78208dec38SEtienne Carriere TEE_PARAM_TYPE_NONE; 79208dec38SEtienne Carriere } 80208dec38SEtienne Carriere 81208dec38SEtienne Carriere static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index) 82208dec38SEtienne Carriere { 83208dec38SEtienne Carriere switch (TEE_PARAM_TYPE_GET(ptypes, index)) { 84208dec38SEtienne Carriere case TEE_PARAM_TYPE_MEMREF_INPUT: 85208dec38SEtienne Carriere case TEE_PARAM_TYPE_MEMREF_OUTPUT: 86208dec38SEtienne Carriere case TEE_PARAM_TYPE_MEMREF_INOUT: 87208dec38SEtienne Carriere return true; 88208dec38SEtienne Carriere default: 89208dec38SEtienne Carriere return false; 90208dec38SEtienne Carriere } 91208dec38SEtienne Carriere } 92208dec38SEtienne Carriere 93208dec38SEtienne Carriere static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index) 94208dec38SEtienne Carriere { 95208dec38SEtienne Carriere return TEE_PARAM_TYPE_GET(ptypes, index) == 96208dec38SEtienne Carriere TEE_PARAM_TYPE_MEMREF_INPUT; 97208dec38SEtienne Carriere } 98208dec38SEtienne Carriere 99208dec38SEtienne Carriere static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index) 100208dec38SEtienne Carriere { 101208dec38SEtienne Carriere return TEE_PARAM_TYPE_GET(ptypes, index) == 102208dec38SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT; 103208dec38SEtienne Carriere } 104208dec38SEtienne Carriere 1056ea5aa6cSEtienne Carriere /* 106f8a3a2c4SEtienne Carriere * Entry point for PKCS11 TA commands 107208dec38SEtienne Carriere * 108208dec38SEtienne Carriere * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized 109208dec38SEtienne Carriere * arguments for the invoked command while the output data is used to send 110208dec38SEtienne Carriere * back to the client a PKCS11 finer status ID than the GPD TEE result codes 111208dec38SEtienne Carriere * Client shall check the status ID from the parameter #0 output buffer together 112208dec38SEtienne Carriere * with the GPD TEE result code. 113f8a3a2c4SEtienne Carriere */ 114e084583eSEtienne Carriere TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd, 1156ea5aa6cSEtienne Carriere uint32_t ptypes, 1166ea5aa6cSEtienne Carriere TEE_Param params[TEE_NUM_PARAMS]) 117f8a3a2c4SEtienne Carriere { 118e084583eSEtienne Carriere struct pkcs11_client *client = tee_session2client(tee_session); 119d34f3266SEtienne Carriere uint32_t rc = 0; 120f8a3a2c4SEtienne Carriere 121e084583eSEtienne Carriere if (!client) 122e084583eSEtienne Carriere return TEE_ERROR_SECURITY; 123e084583eSEtienne Carriere 124208dec38SEtienne Carriere /* All command handlers will check only against 4 parameters */ 125208dec38SEtienne Carriere COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4); 126208dec38SEtienne Carriere 127208dec38SEtienne Carriere /* 128208dec38SEtienne Carriere * Param#0 must be either an output or an inout memref as used to 129208dec38SEtienne Carriere * store the output return value for the invoked command. 130208dec38SEtienne Carriere */ 1316ea5aa6cSEtienne Carriere switch (TEE_PARAM_TYPE_GET(ptypes, 0)) { 1326ea5aa6cSEtienne Carriere case TEE_PARAM_TYPE_MEMREF_OUTPUT: 133208dec38SEtienne Carriere case TEE_PARAM_TYPE_MEMREF_INOUT: 13437d01a77SEtienne Carriere if (params[0].memref.size < sizeof(rc)) 135208dec38SEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 1366ea5aa6cSEtienne Carriere break; 1376ea5aa6cSEtienne Carriere default: 1386ea5aa6cSEtienne Carriere return TEE_ERROR_BAD_PARAMETERS; 1396ea5aa6cSEtienne Carriere } 1406ea5aa6cSEtienne Carriere 141208dec38SEtienne Carriere DMSG("%s p#0 %"PRIu32"@%p, p#1 %s %"PRIu32"@%p, p#2 %s %"PRIu32"@%p", 14260290f69SEtienne Carriere id2str_ta_cmd(cmd), 143208dec38SEtienne Carriere params[0].memref.size, params[0].memref.buffer, 144208dec38SEtienne Carriere param_is_input(ptypes, 1) ? "in" : 145208dec38SEtienne Carriere param_is_output(ptypes, 1) ? "out" : "---", 146208dec38SEtienne Carriere param_is_memref(ptypes, 1) ? params[1].memref.size : 0, 147208dec38SEtienne Carriere param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL, 148208dec38SEtienne Carriere param_is_input(ptypes, 2) ? "in" : 149208dec38SEtienne Carriere param_is_output(ptypes, 2) ? "out" : "---", 150208dec38SEtienne Carriere param_is_memref(ptypes, 2) ? params[2].memref.size : 0, 151208dec38SEtienne Carriere param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL); 15260290f69SEtienne Carriere 1536ea5aa6cSEtienne Carriere switch (cmd) { 1546ea5aa6cSEtienne Carriere case PKCS11_CMD_PING: 155208dec38SEtienne Carriere rc = entry_ping(ptypes, params); 1566ea5aa6cSEtienne Carriere break; 1576ea5aa6cSEtienne Carriere 15822ac6984SEtienne Carriere case PKCS11_CMD_SLOT_LIST: 15922ac6984SEtienne Carriere rc = entry_ck_slot_list(ptypes, params); 16022ac6984SEtienne Carriere break; 161ce94efefSEtienne Carriere case PKCS11_CMD_SLOT_INFO: 162ce94efefSEtienne Carriere rc = entry_ck_slot_info(ptypes, params); 163ce94efefSEtienne Carriere break; 164030e7392SEtienne Carriere case PKCS11_CMD_TOKEN_INFO: 165030e7392SEtienne Carriere rc = entry_ck_token_info(ptypes, params); 166030e7392SEtienne Carriere break; 1676f74919dSEtienne Carriere case PKCS11_CMD_MECHANISM_IDS: 1686f74919dSEtienne Carriere rc = entry_ck_token_mecha_ids(ptypes, params); 1696f74919dSEtienne Carriere break; 1701d3ebedbSEtienne Carriere case PKCS11_CMD_MECHANISM_INFO: 1711d3ebedbSEtienne Carriere rc = entry_ck_token_mecha_info(ptypes, params); 1721d3ebedbSEtienne Carriere break; 173030e7392SEtienne Carriere 1746e4f8f17SEtienne Carriere case PKCS11_CMD_OPEN_SESSION: 1756e4f8f17SEtienne Carriere rc = entry_ck_open_session(client, ptypes, params); 1766e4f8f17SEtienne Carriere break; 1776e4f8f17SEtienne Carriere case PKCS11_CMD_CLOSE_SESSION: 1786e4f8f17SEtienne Carriere rc = entry_ck_close_session(client, ptypes, params); 1796e4f8f17SEtienne Carriere break; 1806e4f8f17SEtienne Carriere case PKCS11_CMD_CLOSE_ALL_SESSIONS: 1816e4f8f17SEtienne Carriere rc = entry_ck_close_all_sessions(client, ptypes, params); 1826e4f8f17SEtienne Carriere break; 1836e4f8f17SEtienne Carriere case PKCS11_CMD_SESSION_INFO: 1846e4f8f17SEtienne Carriere rc = entry_ck_session_info(client, ptypes, params); 1856e4f8f17SEtienne Carriere break; 1866e4f8f17SEtienne Carriere 187f485be04SJens Wiklander case PKCS11_CMD_INIT_TOKEN: 188f485be04SJens Wiklander rc = entry_ck_token_initialize(ptypes, params); 189f485be04SJens Wiklander break; 190*e8dbd92cSJens Wiklander case PKCS11_CMD_INIT_PIN: 191*e8dbd92cSJens Wiklander rc = entry_ck_init_pin(client, ptypes, params); 192*e8dbd92cSJens Wiklander break; 193f485be04SJens Wiklander 1946ea5aa6cSEtienne Carriere default: 1956ea5aa6cSEtienne Carriere EMSG("Command 0x%"PRIx32" is not supported", cmd); 196f8a3a2c4SEtienne Carriere return TEE_ERROR_NOT_SUPPORTED; 197f8a3a2c4SEtienne Carriere } 1986ea5aa6cSEtienne Carriere 199208dec38SEtienne Carriere DMSG("%s rc 0x%08"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc)); 2006ea5aa6cSEtienne Carriere 201208dec38SEtienne Carriere TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc)); 202208dec38SEtienne Carriere params[0].memref.size = sizeof(rc); 203d34f3266SEtienne Carriere 204208dec38SEtienne Carriere if (rc == PKCS11_CKR_BUFFER_TOO_SMALL) 205208dec38SEtienne Carriere return TEE_ERROR_SHORT_BUFFER; 206208dec38SEtienne Carriere else 207208dec38SEtienne Carriere return TEE_SUCCESS; 2086ea5aa6cSEtienne Carriere } 209