xref: /optee_os/ta/pkcs11/src/entry.c (revision e8dbd92c98f3ad1fddf5a18ccdf9c76a47cff3e8)
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 = &params[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