xref: /optee_os/ta/pkcs11/src/entry.c (revision 689f4e5b067fea8c8c0566e968ef2bf5303b2082)
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 
13b56b3d07SJens Wiklander #include "object.h"
1460290f69SEtienne Carriere #include "pkcs11_helpers.h"
15c84ccd0aSEtienne Carriere #include "pkcs11_token.h"
16512cbf1dSJens Wiklander #include "processing.h"
17f8a3a2c4SEtienne Carriere 
18f8a3a2c4SEtienne Carriere TEE_Result TA_CreateEntryPoint(void)
19f8a3a2c4SEtienne Carriere {
20c84ccd0aSEtienne Carriere 	return pkcs11_init();
21f8a3a2c4SEtienne Carriere }
22f8a3a2c4SEtienne Carriere 
23f8a3a2c4SEtienne Carriere void TA_DestroyEntryPoint(void)
24f8a3a2c4SEtienne Carriere {
25c84ccd0aSEtienne Carriere 	pkcs11_deinit();
26f8a3a2c4SEtienne Carriere }
27f8a3a2c4SEtienne Carriere 
28f8a3a2c4SEtienne Carriere TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types,
29f8a3a2c4SEtienne Carriere 				    TEE_Param __unused params[4],
30e084583eSEtienne Carriere 				    void **tee_session)
31f8a3a2c4SEtienne Carriere {
32e084583eSEtienne Carriere 	struct pkcs11_client *client = register_client();
33e084583eSEtienne Carriere 
34e084583eSEtienne Carriere 	if (!client)
35e084583eSEtienne Carriere 		return TEE_ERROR_OUT_OF_MEMORY;
36e084583eSEtienne Carriere 
37e084583eSEtienne Carriere 	*tee_session = client;
38f8a3a2c4SEtienne Carriere 
39f8a3a2c4SEtienne Carriere 	return TEE_SUCCESS;
40f8a3a2c4SEtienne Carriere }
41f8a3a2c4SEtienne Carriere 
42e084583eSEtienne Carriere void TA_CloseSessionEntryPoint(void *tee_session)
43f8a3a2c4SEtienne Carriere {
44e084583eSEtienne Carriere 	struct pkcs11_client *client = tee_session2client(tee_session);
45e084583eSEtienne Carriere 
46e084583eSEtienne Carriere 	unregister_client(client);
47f8a3a2c4SEtienne Carriere }
48f8a3a2c4SEtienne Carriere 
49f8a3a2c4SEtienne Carriere /*
506ea5aa6cSEtienne Carriere  * Entry point for invocation command PKCS11_CMD_PING
516ea5aa6cSEtienne Carriere  *
52208dec38SEtienne Carriere  * Return a PKCS11_CKR_* value which is also loaded into the output param#0
536ea5aa6cSEtienne Carriere  */
544daf39b3SJens Wiklander static enum pkcs11_rc entry_ping(uint32_t ptypes, TEE_Param *params)
556ea5aa6cSEtienne Carriere {
56208dec38SEtienne Carriere 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
57208dec38SEtienne Carriere 						TEE_PARAM_TYPE_NONE,
58208dec38SEtienne Carriere 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
59208dec38SEtienne Carriere 						TEE_PARAM_TYPE_NONE);
6039b43b78SJens Wiklander 	TEE_Param *out = params + 2;
616ea5aa6cSEtienne Carriere 	const uint32_t ver[] = {
626ea5aa6cSEtienne Carriere 		PKCS11_TA_VERSION_MAJOR,
636ea5aa6cSEtienne Carriere 		PKCS11_TA_VERSION_MINOR,
646ea5aa6cSEtienne Carriere 		PKCS11_TA_VERSION_PATCH,
656ea5aa6cSEtienne Carriere 	};
666ea5aa6cSEtienne Carriere 
67208dec38SEtienne Carriere 	if (ptypes != exp_pt ||
68208dec38SEtienne Carriere 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN ||
69208dec38SEtienne Carriere 	    out->memref.size != sizeof(ver))
70208dec38SEtienne Carriere 		return PKCS11_CKR_ARGUMENTS_BAD;
716ea5aa6cSEtienne Carriere 
726ea5aa6cSEtienne Carriere 	TEE_MemMove(out->memref.buffer, ver, sizeof(ver));
736ea5aa6cSEtienne Carriere 
74d34f3266SEtienne Carriere 	return PKCS11_CKR_OK;
756ea5aa6cSEtienne Carriere }
766ea5aa6cSEtienne Carriere 
77208dec38SEtienne Carriere static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index)
78208dec38SEtienne Carriere {
79208dec38SEtienne Carriere 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
80208dec38SEtienne Carriere 	       TEE_PARAM_TYPE_NONE;
81208dec38SEtienne Carriere }
82208dec38SEtienne Carriere 
83208dec38SEtienne Carriere static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index)
84208dec38SEtienne Carriere {
85208dec38SEtienne Carriere 	switch (TEE_PARAM_TYPE_GET(ptypes, index)) {
86208dec38SEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_INPUT:
87208dec38SEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
88208dec38SEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_INOUT:
89208dec38SEtienne Carriere 		return true;
90208dec38SEtienne Carriere 	default:
91208dec38SEtienne Carriere 		return false;
92208dec38SEtienne Carriere 	}
93208dec38SEtienne Carriere }
94208dec38SEtienne Carriere 
95208dec38SEtienne Carriere static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index)
96208dec38SEtienne Carriere {
97208dec38SEtienne Carriere 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
98208dec38SEtienne Carriere 	       TEE_PARAM_TYPE_MEMREF_INPUT;
99208dec38SEtienne Carriere }
100208dec38SEtienne Carriere 
101208dec38SEtienne Carriere static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index)
102208dec38SEtienne Carriere {
103208dec38SEtienne Carriere 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
104208dec38SEtienne Carriere 	       TEE_PARAM_TYPE_MEMREF_OUTPUT;
105208dec38SEtienne Carriere }
106208dec38SEtienne Carriere 
1076ea5aa6cSEtienne Carriere /*
108f8a3a2c4SEtienne Carriere  * Entry point for PKCS11 TA commands
109208dec38SEtienne Carriere  *
110208dec38SEtienne Carriere  * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized
111208dec38SEtienne Carriere  * arguments for the invoked command while the output data is used to send
112208dec38SEtienne Carriere  * back to the client a PKCS11 finer status ID than the GPD TEE result codes
113208dec38SEtienne Carriere  * Client shall check the status ID from the parameter #0 output buffer together
114208dec38SEtienne Carriere  * with the GPD TEE result code.
115f8a3a2c4SEtienne Carriere  */
116e084583eSEtienne Carriere TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd,
1176ea5aa6cSEtienne Carriere 				      uint32_t ptypes,
1186ea5aa6cSEtienne Carriere 				      TEE_Param params[TEE_NUM_PARAMS])
119f8a3a2c4SEtienne Carriere {
120e084583eSEtienne Carriere 	struct pkcs11_client *client = tee_session2client(tee_session);
121d34f3266SEtienne Carriere 	uint32_t rc = 0;
122f8a3a2c4SEtienne Carriere 
123e084583eSEtienne Carriere 	if (!client)
124e084583eSEtienne Carriere 		return TEE_ERROR_SECURITY;
125e084583eSEtienne Carriere 
126208dec38SEtienne Carriere 	/* All command handlers will check only against 4 parameters */
127208dec38SEtienne Carriere 	COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4);
128208dec38SEtienne Carriere 
129208dec38SEtienne Carriere 	/*
130208dec38SEtienne Carriere 	 * Param#0 must be either an output or an inout memref as used to
131208dec38SEtienne Carriere 	 * store the output return value for the invoked command.
132208dec38SEtienne Carriere 	 */
1336ea5aa6cSEtienne Carriere 	switch (TEE_PARAM_TYPE_GET(ptypes, 0)) {
1346ea5aa6cSEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
135208dec38SEtienne Carriere 	case TEE_PARAM_TYPE_MEMREF_INOUT:
13637d01a77SEtienne Carriere 		if (params[0].memref.size < sizeof(rc))
137208dec38SEtienne Carriere 			return TEE_ERROR_BAD_PARAMETERS;
1386ea5aa6cSEtienne Carriere 		break;
1396ea5aa6cSEtienne Carriere 	default:
1406ea5aa6cSEtienne Carriere 		return TEE_ERROR_BAD_PARAMETERS;
1416ea5aa6cSEtienne Carriere 	}
1426ea5aa6cSEtienne Carriere 
143208dec38SEtienne Carriere 	DMSG("%s p#0 %"PRIu32"@%p, p#1 %s %"PRIu32"@%p, p#2 %s %"PRIu32"@%p",
14460290f69SEtienne Carriere 	     id2str_ta_cmd(cmd),
145208dec38SEtienne Carriere 	     params[0].memref.size, params[0].memref.buffer,
146208dec38SEtienne Carriere 	     param_is_input(ptypes, 1) ? "in" :
147208dec38SEtienne Carriere 	     param_is_output(ptypes, 1) ? "out" : "---",
148208dec38SEtienne Carriere 	     param_is_memref(ptypes, 1) ? params[1].memref.size : 0,
149208dec38SEtienne Carriere 	     param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL,
150208dec38SEtienne Carriere 	     param_is_input(ptypes, 2) ? "in" :
151208dec38SEtienne Carriere 	     param_is_output(ptypes, 2) ? "out" : "---",
152208dec38SEtienne Carriere 	     param_is_memref(ptypes, 2) ? params[2].memref.size : 0,
153208dec38SEtienne Carriere 	     param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL);
15460290f69SEtienne Carriere 
1556ea5aa6cSEtienne Carriere 	switch (cmd) {
1566ea5aa6cSEtienne Carriere 	case PKCS11_CMD_PING:
157208dec38SEtienne Carriere 		rc = entry_ping(ptypes, params);
1586ea5aa6cSEtienne Carriere 		break;
1596ea5aa6cSEtienne Carriere 
16022ac6984SEtienne Carriere 	case PKCS11_CMD_SLOT_LIST:
16122ac6984SEtienne Carriere 		rc = entry_ck_slot_list(ptypes, params);
16222ac6984SEtienne Carriere 		break;
163ce94efefSEtienne Carriere 	case PKCS11_CMD_SLOT_INFO:
164ce94efefSEtienne Carriere 		rc = entry_ck_slot_info(ptypes, params);
165ce94efefSEtienne Carriere 		break;
166030e7392SEtienne Carriere 	case PKCS11_CMD_TOKEN_INFO:
167030e7392SEtienne Carriere 		rc = entry_ck_token_info(ptypes, params);
168030e7392SEtienne Carriere 		break;
1696f74919dSEtienne Carriere 	case PKCS11_CMD_MECHANISM_IDS:
1706f74919dSEtienne Carriere 		rc = entry_ck_token_mecha_ids(ptypes, params);
1716f74919dSEtienne Carriere 		break;
1721d3ebedbSEtienne Carriere 	case PKCS11_CMD_MECHANISM_INFO:
1731d3ebedbSEtienne Carriere 		rc = entry_ck_token_mecha_info(ptypes, params);
1741d3ebedbSEtienne Carriere 		break;
175030e7392SEtienne Carriere 
1766e4f8f17SEtienne Carriere 	case PKCS11_CMD_OPEN_SESSION:
1776e4f8f17SEtienne Carriere 		rc = entry_ck_open_session(client, ptypes, params);
1786e4f8f17SEtienne Carriere 		break;
1796e4f8f17SEtienne Carriere 	case PKCS11_CMD_CLOSE_SESSION:
1806e4f8f17SEtienne Carriere 		rc = entry_ck_close_session(client, ptypes, params);
1816e4f8f17SEtienne Carriere 		break;
1826e4f8f17SEtienne Carriere 	case PKCS11_CMD_CLOSE_ALL_SESSIONS:
1836e4f8f17SEtienne Carriere 		rc = entry_ck_close_all_sessions(client, ptypes, params);
1846e4f8f17SEtienne Carriere 		break;
1856e4f8f17SEtienne Carriere 	case PKCS11_CMD_SESSION_INFO:
1866e4f8f17SEtienne Carriere 		rc = entry_ck_session_info(client, ptypes, params);
1876e4f8f17SEtienne Carriere 		break;
1886e4f8f17SEtienne Carriere 
189f485be04SJens Wiklander 	case PKCS11_CMD_INIT_TOKEN:
190f485be04SJens Wiklander 		rc = entry_ck_token_initialize(ptypes, params);
191f485be04SJens Wiklander 		break;
192e8dbd92cSJens Wiklander 	case PKCS11_CMD_INIT_PIN:
193e8dbd92cSJens Wiklander 		rc = entry_ck_init_pin(client, ptypes, params);
194e8dbd92cSJens Wiklander 		break;
1951dbb91e7SJens Wiklander 	case PKCS11_CMD_SET_PIN:
1961dbb91e7SJens Wiklander 		rc = entry_ck_set_pin(client, ptypes, params);
1971dbb91e7SJens Wiklander 		break;
198f7cc36c0SJens Wiklander 	case PKCS11_CMD_LOGIN:
199f7cc36c0SJens Wiklander 		rc = entry_ck_login(client, ptypes, params);
200f7cc36c0SJens Wiklander 		break;
201f7cc36c0SJens Wiklander 	case PKCS11_CMD_LOGOUT:
202f7cc36c0SJens Wiklander 		rc = entry_ck_logout(client, ptypes, params);
203f7cc36c0SJens Wiklander 		break;
204f485be04SJens Wiklander 
205b56b3d07SJens Wiklander 	case PKCS11_CMD_CREATE_OBJECT:
206b56b3d07SJens Wiklander 		rc = entry_create_object(client, ptypes, params);
207b56b3d07SJens Wiklander 		break;
208b56b3d07SJens Wiklander 	case PKCS11_CMD_DESTROY_OBJECT:
209b56b3d07SJens Wiklander 		rc = entry_destroy_object(client, ptypes, params);
210b56b3d07SJens Wiklander 		break;
211b56b3d07SJens Wiklander 
212512cbf1dSJens Wiklander 	case PKCS11_CMD_ENCRYPT_INIT:
213512cbf1dSJens Wiklander 		rc = entry_processing_init(client, ptypes, params,
214512cbf1dSJens Wiklander 					   PKCS11_FUNCTION_ENCRYPT);
215512cbf1dSJens Wiklander 		break;
216512cbf1dSJens Wiklander 	case PKCS11_CMD_DECRYPT_INIT:
217512cbf1dSJens Wiklander 		rc = entry_processing_init(client, ptypes, params,
218512cbf1dSJens Wiklander 					   PKCS11_FUNCTION_DECRYPT);
219512cbf1dSJens Wiklander 		break;
220512cbf1dSJens Wiklander 	case PKCS11_CMD_ENCRYPT_UPDATE:
221512cbf1dSJens Wiklander 		rc = entry_processing_step(client, ptypes, params,
222512cbf1dSJens Wiklander 					   PKCS11_FUNCTION_ENCRYPT,
223512cbf1dSJens Wiklander 					   PKCS11_FUNC_STEP_UPDATE);
224512cbf1dSJens Wiklander 		break;
225512cbf1dSJens Wiklander 	case PKCS11_CMD_DECRYPT_UPDATE:
226512cbf1dSJens Wiklander 		rc = entry_processing_step(client, ptypes, params,
227512cbf1dSJens Wiklander 					   PKCS11_FUNCTION_DECRYPT,
228512cbf1dSJens Wiklander 					   PKCS11_FUNC_STEP_UPDATE);
229512cbf1dSJens Wiklander 		break;
230512cbf1dSJens Wiklander 	case PKCS11_CMD_ENCRYPT_ONESHOT:
231512cbf1dSJens Wiklander 		rc = entry_processing_step(client, ptypes, params,
232512cbf1dSJens Wiklander 					   PKCS11_FUNCTION_ENCRYPT,
233512cbf1dSJens Wiklander 					   PKCS11_FUNC_STEP_ONESHOT);
234512cbf1dSJens Wiklander 		break;
235512cbf1dSJens Wiklander 	case PKCS11_CMD_DECRYPT_ONESHOT:
236512cbf1dSJens Wiklander 		rc = entry_processing_step(client, ptypes, params,
237512cbf1dSJens Wiklander 					   PKCS11_FUNCTION_DECRYPT,
238512cbf1dSJens Wiklander 					   PKCS11_FUNC_STEP_ONESHOT);
239512cbf1dSJens Wiklander 		break;
240512cbf1dSJens Wiklander 	case PKCS11_CMD_ENCRYPT_FINAL:
241512cbf1dSJens Wiklander 		rc = entry_processing_step(client, ptypes, params,
242512cbf1dSJens Wiklander 					   PKCS11_FUNCTION_ENCRYPT,
243512cbf1dSJens Wiklander 					   PKCS11_FUNC_STEP_FINAL);
244512cbf1dSJens Wiklander 		break;
245512cbf1dSJens Wiklander 	case PKCS11_CMD_DECRYPT_FINAL:
246512cbf1dSJens Wiklander 		rc = entry_processing_step(client, ptypes, params,
247512cbf1dSJens Wiklander 					   PKCS11_FUNCTION_DECRYPT,
248512cbf1dSJens Wiklander 					   PKCS11_FUNC_STEP_FINAL);
249512cbf1dSJens Wiklander 		break;
250*689f4e5bSRuchika Gupta 	case PKCS11_CMD_SIGN_INIT:
251*689f4e5bSRuchika Gupta 		rc = entry_processing_init(client, ptypes, params,
252*689f4e5bSRuchika Gupta 					   PKCS11_FUNCTION_SIGN);
253*689f4e5bSRuchika Gupta 		break;
254*689f4e5bSRuchika Gupta 	case PKCS11_CMD_VERIFY_INIT:
255*689f4e5bSRuchika Gupta 		rc = entry_processing_init(client, ptypes, params,
256*689f4e5bSRuchika Gupta 					   PKCS11_FUNCTION_VERIFY);
257*689f4e5bSRuchika Gupta 		break;
258*689f4e5bSRuchika Gupta 	case PKCS11_CMD_SIGN_ONESHOT:
259*689f4e5bSRuchika Gupta 		rc = entry_processing_step(client, ptypes, params,
260*689f4e5bSRuchika Gupta 					   PKCS11_FUNCTION_SIGN,
261*689f4e5bSRuchika Gupta 					   PKCS11_FUNC_STEP_ONESHOT);
262*689f4e5bSRuchika Gupta 		break;
263*689f4e5bSRuchika Gupta 	case PKCS11_CMD_VERIFY_ONESHOT:
264*689f4e5bSRuchika Gupta 		rc = entry_processing_step(client, ptypes, params,
265*689f4e5bSRuchika Gupta 					   PKCS11_FUNCTION_VERIFY,
266*689f4e5bSRuchika Gupta 					   PKCS11_FUNC_STEP_ONESHOT);
267*689f4e5bSRuchika Gupta 		break;
268*689f4e5bSRuchika Gupta 	case PKCS11_CMD_SIGN_UPDATE:
269*689f4e5bSRuchika Gupta 		rc = entry_processing_step(client, ptypes, params,
270*689f4e5bSRuchika Gupta 					   PKCS11_FUNCTION_SIGN,
271*689f4e5bSRuchika Gupta 					   PKCS11_FUNC_STEP_UPDATE);
272*689f4e5bSRuchika Gupta 		break;
273*689f4e5bSRuchika Gupta 	case PKCS11_CMD_VERIFY_UPDATE:
274*689f4e5bSRuchika Gupta 		rc = entry_processing_step(client, ptypes, params,
275*689f4e5bSRuchika Gupta 					   PKCS11_FUNCTION_VERIFY,
276*689f4e5bSRuchika Gupta 					   PKCS11_FUNC_STEP_UPDATE);
277*689f4e5bSRuchika Gupta 		break;
278*689f4e5bSRuchika Gupta 	case PKCS11_CMD_SIGN_FINAL:
279*689f4e5bSRuchika Gupta 		rc = entry_processing_step(client, ptypes, params,
280*689f4e5bSRuchika Gupta 					   PKCS11_FUNCTION_SIGN,
281*689f4e5bSRuchika Gupta 					   PKCS11_FUNC_STEP_FINAL);
282*689f4e5bSRuchika Gupta 		break;
283*689f4e5bSRuchika Gupta 	case PKCS11_CMD_VERIFY_FINAL:
284*689f4e5bSRuchika Gupta 		rc = entry_processing_step(client, ptypes, params,
285*689f4e5bSRuchika Gupta 					   PKCS11_FUNCTION_VERIFY,
286*689f4e5bSRuchika Gupta 					   PKCS11_FUNC_STEP_FINAL);
287*689f4e5bSRuchika Gupta 		break;
2886ea5aa6cSEtienne Carriere 	default:
289eb8fd7b9SEtienne Carriere 		EMSG("Command %#"PRIx32" is not supported", cmd);
290f8a3a2c4SEtienne Carriere 		return TEE_ERROR_NOT_SUPPORTED;
291f8a3a2c4SEtienne Carriere 	}
2926ea5aa6cSEtienne Carriere 
293eb8fd7b9SEtienne Carriere 	DMSG("%s rc %#"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc));
2946ea5aa6cSEtienne Carriere 
295208dec38SEtienne Carriere 	TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc));
296208dec38SEtienne Carriere 	params[0].memref.size = sizeof(rc);
297d34f3266SEtienne Carriere 
298208dec38SEtienne Carriere 	if (rc == PKCS11_CKR_BUFFER_TOO_SMALL)
299208dec38SEtienne Carriere 		return TEE_ERROR_SHORT_BUFFER;
300208dec38SEtienne Carriere 	else
301208dec38SEtienne Carriere 		return TEE_SUCCESS;
3026ea5aa6cSEtienne Carriere }
303