xref: /optee_os/ta/pkcs11/src/entry.c (revision b56b3d071d79537f0b9c86d26c033d9ed5c0206a)
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 
13*b56b3d07SJens Wiklander #include "object.h"
1460290f69SEtienne Carriere #include "pkcs11_helpers.h"
15c84ccd0aSEtienne Carriere #include "pkcs11_token.h"
16f8a3a2c4SEtienne Carriere 
17f8a3a2c4SEtienne Carriere TEE_Result TA_CreateEntryPoint(void)
18f8a3a2c4SEtienne Carriere {
19c84ccd0aSEtienne Carriere 	return pkcs11_init();
20f8a3a2c4SEtienne Carriere }
21f8a3a2c4SEtienne Carriere 
22f8a3a2c4SEtienne Carriere void TA_DestroyEntryPoint(void)
23f8a3a2c4SEtienne Carriere {
24c84ccd0aSEtienne Carriere 	pkcs11_deinit();
25f8a3a2c4SEtienne Carriere }
26f8a3a2c4SEtienne Carriere 
27f8a3a2c4SEtienne Carriere TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types,
28f8a3a2c4SEtienne Carriere 				    TEE_Param __unused params[4],
29e084583eSEtienne Carriere 				    void **tee_session)
30f8a3a2c4SEtienne Carriere {
31e084583eSEtienne Carriere 	struct pkcs11_client *client = register_client();
32e084583eSEtienne Carriere 
33e084583eSEtienne Carriere 	if (!client)
34e084583eSEtienne Carriere 		return TEE_ERROR_OUT_OF_MEMORY;
35e084583eSEtienne Carriere 
36e084583eSEtienne Carriere 	*tee_session = client;
37f8a3a2c4SEtienne Carriere 
38f8a3a2c4SEtienne Carriere 	return TEE_SUCCESS;
39f8a3a2c4SEtienne Carriere }
40f8a3a2c4SEtienne Carriere 
41e084583eSEtienne Carriere void TA_CloseSessionEntryPoint(void *tee_session)
42f8a3a2c4SEtienne Carriere {
43e084583eSEtienne Carriere 	struct pkcs11_client *client = tee_session2client(tee_session);
44e084583eSEtienne Carriere 
45e084583eSEtienne Carriere 	unregister_client(client);
46f8a3a2c4SEtienne Carriere }
47f8a3a2c4SEtienne Carriere 
48f8a3a2c4SEtienne Carriere /*
496ea5aa6cSEtienne Carriere  * Entry point for invocation command PKCS11_CMD_PING
506ea5aa6cSEtienne Carriere  *
51208dec38SEtienne Carriere  * Return a PKCS11_CKR_* value which is also loaded into the output param#0
526ea5aa6cSEtienne Carriere  */
534daf39b3SJens Wiklander static enum pkcs11_rc entry_ping(uint32_t ptypes, TEE_Param *params)
546ea5aa6cSEtienne Carriere {
55208dec38SEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
56208dec38SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
57208dec38SEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
58208dec38SEtienne Carriere 						TEE_PARAM_TYPE_NONE);
5939b43b78SJens Wiklander 	TEE_Param *out = params + 2;
606ea5aa6cSEtienne Carriere 	const uint32_t ver[] = {
616ea5aa6cSEtienne Carriere 		PKCS11_TA_VERSION_MAJOR,
626ea5aa6cSEtienne Carriere 		PKCS11_TA_VERSION_MINOR,
636ea5aa6cSEtienne Carriere 		PKCS11_TA_VERSION_PATCH,
646ea5aa6cSEtienne Carriere 	};
656ea5aa6cSEtienne Carriere 
66208dec38SEtienne Carriere 	if (ptypes != exp_pt ||
67208dec38SEtienne Carriere 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN ||
68208dec38SEtienne Carriere 	    out->memref.size != sizeof(ver))
69208dec38SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
706ea5aa6cSEtienne Carriere 
716ea5aa6cSEtienne Carriere 	TEE_MemMove(out->memref.buffer, ver, sizeof(ver));
726ea5aa6cSEtienne Carriere 
73d34f3266SEtienne Carriere 	return PKCS11_CKR_OK;
746ea5aa6cSEtienne Carriere }
756ea5aa6cSEtienne Carriere 
76208dec38SEtienne Carriere static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index)
77208dec38SEtienne Carriere {
78208dec38SEtienne Carriere 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
79208dec38SEtienne Carriere 	       TEE_PARAM_TYPE_NONE;
80208dec38SEtienne Carriere }
81208dec38SEtienne Carriere 
82208dec38SEtienne Carriere static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index)
83208dec38SEtienne Carriere {
84208dec38SEtienne Carriere 	switch (TEE_PARAM_TYPE_GET(ptypes, index)) {
85208dec38SEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_INPUT:
86208dec38SEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
87208dec38SEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_INOUT:
88208dec38SEtienne Carriere 		return true;
89208dec38SEtienne Carriere 	default:
90208dec38SEtienne Carriere 		return false;
91208dec38SEtienne Carriere 	}
92208dec38SEtienne Carriere }
93208dec38SEtienne Carriere 
94208dec38SEtienne Carriere static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index)
95208dec38SEtienne Carriere {
96208dec38SEtienne Carriere 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
97208dec38SEtienne Carriere 	       TEE_PARAM_TYPE_MEMREF_INPUT;
98208dec38SEtienne Carriere }
99208dec38SEtienne Carriere 
100208dec38SEtienne Carriere static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index)
101208dec38SEtienne Carriere {
102208dec38SEtienne Carriere 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
103208dec38SEtienne Carriere 	       TEE_PARAM_TYPE_MEMREF_OUTPUT;
104208dec38SEtienne Carriere }
105208dec38SEtienne Carriere 
1066ea5aa6cSEtienne Carriere /*
107f8a3a2c4SEtienne Carriere  * Entry point for PKCS11 TA commands
108208dec38SEtienne Carriere  *
109208dec38SEtienne Carriere  * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized
110208dec38SEtienne Carriere  * arguments for the invoked command while the output data is used to send
111208dec38SEtienne Carriere  * back to the client a PKCS11 finer status ID than the GPD TEE result codes
112208dec38SEtienne Carriere  * Client shall check the status ID from the parameter #0 output buffer together
113208dec38SEtienne Carriere  * with the GPD TEE result code.
114f8a3a2c4SEtienne Carriere  */
115e084583eSEtienne Carriere TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd,
1166ea5aa6cSEtienne Carriere 				      uint32_t ptypes,
1176ea5aa6cSEtienne Carriere 				      TEE_Param params[TEE_NUM_PARAMS])
118f8a3a2c4SEtienne Carriere {
119e084583eSEtienne Carriere 	struct pkcs11_client *client = tee_session2client(tee_session);
120d34f3266SEtienne Carriere 	uint32_t rc = 0;
121f8a3a2c4SEtienne Carriere 
122e084583eSEtienne Carriere 	if (!client)
123e084583eSEtienne Carriere 		return TEE_ERROR_SECURITY;
124e084583eSEtienne Carriere 
125208dec38SEtienne Carriere 	/* All command handlers will check only against 4 parameters */
126208dec38SEtienne Carriere 	COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4);
127208dec38SEtienne Carriere 
128208dec38SEtienne Carriere 	/*
129208dec38SEtienne Carriere 	 * Param#0 must be either an output or an inout memref as used to
130208dec38SEtienne Carriere 	 * store the output return value for the invoked command.
131208dec38SEtienne Carriere 	 */
1326ea5aa6cSEtienne Carriere 	switch (TEE_PARAM_TYPE_GET(ptypes, 0)) {
1336ea5aa6cSEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
134208dec38SEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_INOUT:
13537d01a77SEtienne Carriere 		if (params[0].memref.size < sizeof(rc))
136208dec38SEtienne Carriere 			return TEE_ERROR_BAD_PARAMETERS;
1376ea5aa6cSEtienne Carriere 		break;
1386ea5aa6cSEtienne Carriere 	default:
1396ea5aa6cSEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
1406ea5aa6cSEtienne Carriere 	}
1416ea5aa6cSEtienne Carriere 
142208dec38SEtienne Carriere 	DMSG("%s p#0 %"PRIu32"@%p, p#1 %s %"PRIu32"@%p, p#2 %s %"PRIu32"@%p",
14360290f69SEtienne Carriere 	     id2str_ta_cmd(cmd),
144208dec38SEtienne Carriere 	     params[0].memref.size, params[0].memref.buffer,
145208dec38SEtienne Carriere 	     param_is_input(ptypes, 1) ? "in" :
146208dec38SEtienne Carriere 	     param_is_output(ptypes, 1) ? "out" : "---",
147208dec38SEtienne Carriere 	     param_is_memref(ptypes, 1) ? params[1].memref.size : 0,
148208dec38SEtienne Carriere 	     param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL,
149208dec38SEtienne Carriere 	     param_is_input(ptypes, 2) ? "in" :
150208dec38SEtienne Carriere 	     param_is_output(ptypes, 2) ? "out" : "---",
151208dec38SEtienne Carriere 	     param_is_memref(ptypes, 2) ? params[2].memref.size : 0,
152208dec38SEtienne Carriere 	     param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL);
15360290f69SEtienne Carriere 
1546ea5aa6cSEtienne Carriere 	switch (cmd) {
1556ea5aa6cSEtienne Carriere 	case PKCS11_CMD_PING:
156208dec38SEtienne Carriere 		rc = entry_ping(ptypes, params);
1576ea5aa6cSEtienne Carriere 		break;
1586ea5aa6cSEtienne Carriere 
15922ac6984SEtienne Carriere 	case PKCS11_CMD_SLOT_LIST:
16022ac6984SEtienne Carriere 		rc = entry_ck_slot_list(ptypes, params);
16122ac6984SEtienne Carriere 		break;
162ce94efefSEtienne Carriere 	case PKCS11_CMD_SLOT_INFO:
163ce94efefSEtienne Carriere 		rc = entry_ck_slot_info(ptypes, params);
164ce94efefSEtienne Carriere 		break;
165030e7392SEtienne Carriere 	case PKCS11_CMD_TOKEN_INFO:
166030e7392SEtienne Carriere 		rc = entry_ck_token_info(ptypes, params);
167030e7392SEtienne Carriere 		break;
1686f74919dSEtienne Carriere 	case PKCS11_CMD_MECHANISM_IDS:
1696f74919dSEtienne Carriere 		rc = entry_ck_token_mecha_ids(ptypes, params);
1706f74919dSEtienne Carriere 		break;
1711d3ebedbSEtienne Carriere 	case PKCS11_CMD_MECHANISM_INFO:
1721d3ebedbSEtienne Carriere 		rc = entry_ck_token_mecha_info(ptypes, params);
1731d3ebedbSEtienne Carriere 		break;
174030e7392SEtienne Carriere 
1756e4f8f17SEtienne Carriere 	case PKCS11_CMD_OPEN_SESSION:
1766e4f8f17SEtienne Carriere 		rc = entry_ck_open_session(client, ptypes, params);
1776e4f8f17SEtienne Carriere 		break;
1786e4f8f17SEtienne Carriere 	case PKCS11_CMD_CLOSE_SESSION:
1796e4f8f17SEtienne Carriere 		rc = entry_ck_close_session(client, ptypes, params);
1806e4f8f17SEtienne Carriere 		break;
1816e4f8f17SEtienne Carriere 	case PKCS11_CMD_CLOSE_ALL_SESSIONS:
1826e4f8f17SEtienne Carriere 		rc = entry_ck_close_all_sessions(client, ptypes, params);
1836e4f8f17SEtienne Carriere 		break;
1846e4f8f17SEtienne Carriere 	case PKCS11_CMD_SESSION_INFO:
1856e4f8f17SEtienne Carriere 		rc = entry_ck_session_info(client, ptypes, params);
1866e4f8f17SEtienne Carriere 		break;
1876e4f8f17SEtienne Carriere 
188f485be04SJens Wiklander 	case PKCS11_CMD_INIT_TOKEN:
189f485be04SJens Wiklander 		rc = entry_ck_token_initialize(ptypes, params);
190f485be04SJens Wiklander 		break;
191e8dbd92cSJens Wiklander 	case PKCS11_CMD_INIT_PIN:
192e8dbd92cSJens Wiklander 		rc = entry_ck_init_pin(client, ptypes, params);
193e8dbd92cSJens Wiklander 		break;
1941dbb91e7SJens Wiklander 	case PKCS11_CMD_SET_PIN:
1951dbb91e7SJens Wiklander 		rc = entry_ck_set_pin(client, ptypes, params);
1961dbb91e7SJens Wiklander 		break;
197f7cc36c0SJens Wiklander 	case PKCS11_CMD_LOGIN:
198f7cc36c0SJens Wiklander 		rc = entry_ck_login(client, ptypes, params);
199f7cc36c0SJens Wiklander 		break;
200f7cc36c0SJens Wiklander 	case PKCS11_CMD_LOGOUT:
201f7cc36c0SJens Wiklander 		rc = entry_ck_logout(client, ptypes, params);
202f7cc36c0SJens Wiklander 		break;
203f485be04SJens Wiklander 
204*b56b3d07SJens Wiklander 	case PKCS11_CMD_CREATE_OBJECT:
205*b56b3d07SJens Wiklander 		rc = entry_create_object(client, ptypes, params);
206*b56b3d07SJens Wiklander 		break;
207*b56b3d07SJens Wiklander 	case PKCS11_CMD_DESTROY_OBJECT:
208*b56b3d07SJens Wiklander 		rc = entry_destroy_object(client, ptypes, params);
209*b56b3d07SJens Wiklander 		break;
210*b56b3d07SJens Wiklander 
2116ea5aa6cSEtienne Carriere 	default:
212eb8fd7b9SEtienne Carriere 		EMSG("Command %#"PRIx32" is not supported", cmd);
213f8a3a2c4SEtienne Carriere 		return TEE_ERROR_NOT_SUPPORTED;
214f8a3a2c4SEtienne Carriere 	}
2156ea5aa6cSEtienne Carriere 
216eb8fd7b9SEtienne Carriere 	DMSG("%s rc %#"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc));
2176ea5aa6cSEtienne Carriere 
218208dec38SEtienne Carriere 	TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc));
219208dec38SEtienne Carriere 	params[0].memref.size = sizeof(rc);
220d34f3266SEtienne Carriere 
221208dec38SEtienne Carriere 	if (rc == PKCS11_CKR_BUFFER_TOO_SMALL)
222208dec38SEtienne Carriere 		return TEE_ERROR_SHORT_BUFFER;
223208dec38SEtienne Carriere 	else
224208dec38SEtienne Carriere 		return TEE_SUCCESS;
2256ea5aa6cSEtienne Carriere }
226