xref: /optee_os/ta/pkcs11/src/entry.c (revision f86aa9e1925ef129e92324b3d5e1d4c7f0a03e87)
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 "object.h"
14 #include "pkcs11_helpers.h"
15 #include "pkcs11_token.h"
16 
17 TEE_Result TA_CreateEntryPoint(void)
18 {
19 	return pkcs11_init();
20 }
21 
22 void TA_DestroyEntryPoint(void)
23 {
24 	pkcs11_deinit();
25 }
26 
27 TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types,
28 				    TEE_Param __unused params[4],
29 				    void **tee_session)
30 {
31 	struct pkcs11_client *client = register_client();
32 
33 	if (!client)
34 		return TEE_ERROR_OUT_OF_MEMORY;
35 
36 	*tee_session = client;
37 
38 	return TEE_SUCCESS;
39 }
40 
41 void TA_CloseSessionEntryPoint(void *tee_session)
42 {
43 	struct pkcs11_client *client = tee_session2client(tee_session);
44 
45 	unregister_client(client);
46 }
47 
48 /*
49  * Entry point for invocation command PKCS11_CMD_PING
50  *
51  * Return a PKCS11_CKR_* value which is also loaded into the output param#0
52  */
53 static enum pkcs11_rc entry_ping(uint32_t ptypes, TEE_Param *params)
54 {
55 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
56 						TEE_PARAM_TYPE_NONE,
57 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
58 						TEE_PARAM_TYPE_NONE);
59 	TEE_Param *out = params + 2;
60 	const uint32_t ver[] = {
61 		PKCS11_TA_VERSION_MAJOR,
62 		PKCS11_TA_VERSION_MINOR,
63 		PKCS11_TA_VERSION_PATCH,
64 	};
65 
66 	if (ptypes != exp_pt ||
67 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN ||
68 	    out->memref.size != sizeof(ver))
69 		return PKCS11_CKR_ARGUMENTS_BAD;
70 
71 	TEE_MemMove(out->memref.buffer, ver, sizeof(ver));
72 
73 	return PKCS11_CKR_OK;
74 }
75 
76 static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index)
77 {
78 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
79 	       TEE_PARAM_TYPE_NONE;
80 }
81 
82 static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index)
83 {
84 	switch (TEE_PARAM_TYPE_GET(ptypes, index)) {
85 	case TEE_PARAM_TYPE_MEMREF_INPUT:
86 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
87 	case TEE_PARAM_TYPE_MEMREF_INOUT:
88 		return true;
89 	default:
90 		return false;
91 	}
92 }
93 
94 static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index)
95 {
96 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
97 	       TEE_PARAM_TYPE_MEMREF_INPUT;
98 }
99 
100 static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index)
101 {
102 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
103 	       TEE_PARAM_TYPE_MEMREF_OUTPUT;
104 }
105 
106 /*
107  * Entry point for PKCS11 TA commands
108  *
109  * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized
110  * arguments for the invoked command while the output data is used to send
111  * back to the client a PKCS11 finer status ID than the GPD TEE result codes
112  * Client shall check the status ID from the parameter #0 output buffer together
113  * with the GPD TEE result code.
114  */
115 TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd,
116 				      uint32_t ptypes,
117 				      TEE_Param params[TEE_NUM_PARAMS])
118 {
119 	struct pkcs11_client *client = tee_session2client(tee_session);
120 	uint32_t rc = 0;
121 
122 	if (!client)
123 		return TEE_ERROR_SECURITY;
124 
125 	/* All command handlers will check only against 4 parameters */
126 	COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4);
127 
128 	/*
129 	 * Param#0 must be either an output or an inout memref as used to
130 	 * store the output return value for the invoked command.
131 	 */
132 	switch (TEE_PARAM_TYPE_GET(ptypes, 0)) {
133 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
134 	case TEE_PARAM_TYPE_MEMREF_INOUT:
135 		if (params[0].memref.size < sizeof(rc))
136 			return TEE_ERROR_BAD_PARAMETERS;
137 		break;
138 	default:
139 		return TEE_ERROR_BAD_PARAMETERS;
140 	}
141 
142 	DMSG("%s p#0 %"PRIu32"@%p, p#1 %s %"PRIu32"@%p, p#2 %s %"PRIu32"@%p",
143 	     id2str_ta_cmd(cmd),
144 	     params[0].memref.size, params[0].memref.buffer,
145 	     param_is_input(ptypes, 1) ? "in" :
146 	     param_is_output(ptypes, 1) ? "out" : "---",
147 	     param_is_memref(ptypes, 1) ? params[1].memref.size : 0,
148 	     param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL,
149 	     param_is_input(ptypes, 2) ? "in" :
150 	     param_is_output(ptypes, 2) ? "out" : "---",
151 	     param_is_memref(ptypes, 2) ? params[2].memref.size : 0,
152 	     param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL);
153 
154 	switch (cmd) {
155 	case PKCS11_CMD_PING:
156 		rc = entry_ping(ptypes, params);
157 		break;
158 
159 	case PKCS11_CMD_SLOT_LIST:
160 		rc = entry_ck_slot_list(ptypes, params);
161 		break;
162 	case PKCS11_CMD_SLOT_INFO:
163 		rc = entry_ck_slot_info(ptypes, params);
164 		break;
165 	case PKCS11_CMD_TOKEN_INFO:
166 		rc = entry_ck_token_info(ptypes, params);
167 		break;
168 	case PKCS11_CMD_MECHANISM_IDS:
169 		rc = entry_ck_token_mecha_ids(ptypes, params);
170 		break;
171 	case PKCS11_CMD_MECHANISM_INFO:
172 		rc = entry_ck_token_mecha_info(ptypes, params);
173 		break;
174 
175 	case PKCS11_CMD_OPEN_SESSION:
176 		rc = entry_ck_open_session(client, ptypes, params);
177 		break;
178 	case PKCS11_CMD_CLOSE_SESSION:
179 		rc = entry_ck_close_session(client, ptypes, params);
180 		break;
181 	case PKCS11_CMD_CLOSE_ALL_SESSIONS:
182 		rc = entry_ck_close_all_sessions(client, ptypes, params);
183 		break;
184 	case PKCS11_CMD_SESSION_INFO:
185 		rc = entry_ck_session_info(client, ptypes, params);
186 		break;
187 
188 	case PKCS11_CMD_INIT_TOKEN:
189 		rc = entry_ck_token_initialize(ptypes, params);
190 		break;
191 	case PKCS11_CMD_INIT_PIN:
192 		rc = entry_ck_init_pin(client, ptypes, params);
193 		break;
194 	case PKCS11_CMD_SET_PIN:
195 		rc = entry_ck_set_pin(client, ptypes, params);
196 		break;
197 	case PKCS11_CMD_LOGIN:
198 		rc = entry_ck_login(client, ptypes, params);
199 		break;
200 	case PKCS11_CMD_LOGOUT:
201 		rc = entry_ck_logout(client, ptypes, params);
202 		break;
203 
204 	case PKCS11_CMD_CREATE_OBJECT:
205 		rc = entry_create_object(client, ptypes, params);
206 		break;
207 	case PKCS11_CMD_DESTROY_OBJECT:
208 		rc = entry_destroy_object(client, ptypes, params);
209 		break;
210 
211 	default:
212 		EMSG("Command %#"PRIx32" is not supported", cmd);
213 		return TEE_ERROR_NOT_SUPPORTED;
214 	}
215 
216 	DMSG("%s rc %#"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc));
217 
218 	TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc));
219 	params[0].memref.size = sizeof(rc);
220 
221 	if (rc == PKCS11_CKR_BUFFER_TOO_SMALL)
222 		return TEE_ERROR_SHORT_BUFFER;
223 	else
224 		return TEE_SUCCESS;
225 }
226