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 #include "processing.h"
17 
TA_CreateEntryPoint(void)18 TEE_Result TA_CreateEntryPoint(void)
19 {
20 	return pkcs11_init();
21 }
22 
TA_DestroyEntryPoint(void)23 void TA_DestroyEntryPoint(void)
24 {
25 	pkcs11_deinit();
26 }
27 
TA_OpenSessionEntryPoint(uint32_t __unused param_types,TEE_Param __unused params[4],void ** tee_session)28 TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types,
29 				    TEE_Param __unused params[4],
30 				    void **tee_session)
31 {
32 	struct pkcs11_client *client = register_client();
33 
34 	if (!client)
35 		return TEE_ERROR_OUT_OF_MEMORY;
36 
37 	*tee_session = client;
38 
39 	return TEE_SUCCESS;
40 }
41 
TA_CloseSessionEntryPoint(void * tee_session)42 void TA_CloseSessionEntryPoint(void *tee_session)
43 {
44 	struct pkcs11_client *client = tee_session2client(tee_session);
45 
46 	unregister_client(client);
47 }
48 
49 /*
50  * Entry point for invocation command PKCS11_CMD_PING
51  *
52  * Return a PKCS11_CKR_* value which is also loaded into the output param#0
53  */
entry_ping(uint32_t ptypes,TEE_Param * params)54 static enum pkcs11_rc entry_ping(uint32_t ptypes, TEE_Param *params)
55 {
56 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
57 						TEE_PARAM_TYPE_NONE,
58 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
59 						TEE_PARAM_TYPE_NONE);
60 	TEE_Param *out = params + 2;
61 	const uint32_t ver[] = {
62 		PKCS11_TA_VERSION_MAJOR,
63 		PKCS11_TA_VERSION_MINOR,
64 		PKCS11_TA_VERSION_PATCH,
65 	};
66 
67 	if (ptypes != exp_pt ||
68 	    params[0].memref.size != TEE_PARAM0_SIZE_MIN ||
69 	    out->memref.size != sizeof(ver))
70 		return PKCS11_CKR_ARGUMENTS_BAD;
71 
72 	TEE_MemMove(out->memref.buffer, ver, sizeof(ver));
73 
74 	return PKCS11_CKR_OK;
75 }
76 
param_is_none(uint32_t ptypes,unsigned int index)77 static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index)
78 {
79 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
80 	       TEE_PARAM_TYPE_NONE;
81 }
82 
param_is_memref(uint32_t ptypes,unsigned int index)83 static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index)
84 {
85 	switch (TEE_PARAM_TYPE_GET(ptypes, index)) {
86 	case TEE_PARAM_TYPE_MEMREF_INPUT:
87 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
88 	case TEE_PARAM_TYPE_MEMREF_INOUT:
89 		return true;
90 	default:
91 		return false;
92 	}
93 }
94 
param_is_input(uint32_t ptypes,unsigned int index)95 static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index)
96 {
97 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
98 	       TEE_PARAM_TYPE_MEMREF_INPUT;
99 }
100 
param_is_output(uint32_t ptypes,unsigned int index)101 static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index)
102 {
103 	return TEE_PARAM_TYPE_GET(ptypes, index) ==
104 	       TEE_PARAM_TYPE_MEMREF_OUTPUT;
105 }
106 
107 /*
108  * Entry point for PKCS11 TA commands
109  *
110  * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized
111  * arguments for the invoked command while the output data is used to send
112  * back to the client a PKCS11 finer status ID than the GPD TEE result codes
113  * Client shall check the status ID from the parameter #0 output buffer together
114  * with the GPD TEE result code.
115  */
TA_InvokeCommandEntryPoint(void * tee_session,uint32_t cmd,uint32_t ptypes,TEE_Param params[TEE_NUM_PARAMS])116 TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd,
117 				      uint32_t ptypes,
118 				      TEE_Param params[TEE_NUM_PARAMS])
119 {
120 	struct pkcs11_client *client = tee_session2client(tee_session);
121 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
122 
123 	if (!client)
124 		return TEE_ERROR_SECURITY;
125 
126 	/* All command handlers will check only against 4 parameters */
127 	COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4);
128 
129 	/*
130 	 * Param#0 must be either an output or an inout memref as used to
131 	 * store the output return value for the invoked command.
132 	 */
133 	switch (TEE_PARAM_TYPE_GET(ptypes, 0)) {
134 	case TEE_PARAM_TYPE_MEMREF_OUTPUT:
135 	case TEE_PARAM_TYPE_MEMREF_INOUT:
136 		if (params[0].memref.size < sizeof(rc))
137 			return TEE_ERROR_BAD_PARAMETERS;
138 		break;
139 	default:
140 		return TEE_ERROR_BAD_PARAMETERS;
141 	}
142 
143 	DMSG("%s p#0 %"PRIu32"@%p, p#1 %s %"PRIu32"@%p, p#2 %s %"PRIu32"@%p",
144 	     id2str_ta_cmd(cmd),
145 	     params[0].memref.size, params[0].memref.buffer,
146 	     param_is_input(ptypes, 1) ? "in" :
147 	     param_is_output(ptypes, 1) ? "out" : "---",
148 	     param_is_memref(ptypes, 1) ? params[1].memref.size : 0,
149 	     param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL,
150 	     param_is_input(ptypes, 2) ? "in" :
151 	     param_is_output(ptypes, 2) ? "out" : "---",
152 	     param_is_memref(ptypes, 2) ? params[2].memref.size : 0,
153 	     param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL);
154 
155 	switch (cmd) {
156 	case PKCS11_CMD_PING:
157 		rc = entry_ping(ptypes, params);
158 		break;
159 
160 	case PKCS11_CMD_SLOT_LIST:
161 		rc = entry_ck_slot_list(ptypes, params);
162 		break;
163 	case PKCS11_CMD_SLOT_INFO:
164 		rc = entry_ck_slot_info(ptypes, params);
165 		break;
166 	case PKCS11_CMD_TOKEN_INFO:
167 		rc = entry_ck_token_info(ptypes, params);
168 		break;
169 	case PKCS11_CMD_MECHANISM_IDS:
170 		rc = entry_ck_token_mecha_ids(ptypes, params);
171 		break;
172 	case PKCS11_CMD_MECHANISM_INFO:
173 		rc = entry_ck_token_mecha_info(ptypes, params);
174 		break;
175 
176 	case PKCS11_CMD_OPEN_SESSION:
177 		rc = entry_ck_open_session(client, ptypes, params);
178 		break;
179 	case PKCS11_CMD_CLOSE_SESSION:
180 		rc = entry_ck_close_session(client, ptypes, params);
181 		break;
182 	case PKCS11_CMD_CLOSE_ALL_SESSIONS:
183 		rc = entry_ck_close_all_sessions(client, ptypes, params);
184 		break;
185 	case PKCS11_CMD_SESSION_INFO:
186 		rc = entry_ck_session_info(client, ptypes, params);
187 		break;
188 
189 	case PKCS11_CMD_INIT_TOKEN:
190 		rc = entry_ck_token_initialize(ptypes, params);
191 		break;
192 	case PKCS11_CMD_INIT_PIN:
193 		rc = entry_ck_init_pin(client, ptypes, params);
194 		break;
195 	case PKCS11_CMD_SET_PIN:
196 		rc = entry_ck_set_pin(client, ptypes, params);
197 		break;
198 	case PKCS11_CMD_LOGIN:
199 		rc = entry_ck_login(client, ptypes, params);
200 		break;
201 	case PKCS11_CMD_LOGOUT:
202 		rc = entry_ck_logout(client, ptypes, params);
203 		break;
204 
205 	case PKCS11_CMD_CREATE_OBJECT:
206 		rc = entry_create_object(client, ptypes, params);
207 		break;
208 	case PKCS11_CMD_DESTROY_OBJECT:
209 		rc = entry_destroy_object(client, ptypes, params);
210 		break;
211 
212 	case PKCS11_CMD_ENCRYPT_INIT:
213 		rc = entry_processing_init(client, ptypes, params,
214 					   PKCS11_FUNCTION_ENCRYPT);
215 		break;
216 	case PKCS11_CMD_DECRYPT_INIT:
217 		rc = entry_processing_init(client, ptypes, params,
218 					   PKCS11_FUNCTION_DECRYPT);
219 		break;
220 	case PKCS11_CMD_ENCRYPT_UPDATE:
221 		rc = entry_processing_step(client, ptypes, params,
222 					   PKCS11_FUNCTION_ENCRYPT,
223 					   PKCS11_FUNC_STEP_UPDATE);
224 		break;
225 	case PKCS11_CMD_DECRYPT_UPDATE:
226 		rc = entry_processing_step(client, ptypes, params,
227 					   PKCS11_FUNCTION_DECRYPT,
228 					   PKCS11_FUNC_STEP_UPDATE);
229 		break;
230 	case PKCS11_CMD_ENCRYPT_ONESHOT:
231 		rc = entry_processing_step(client, ptypes, params,
232 					   PKCS11_FUNCTION_ENCRYPT,
233 					   PKCS11_FUNC_STEP_ONESHOT);
234 		break;
235 	case PKCS11_CMD_DECRYPT_ONESHOT:
236 		rc = entry_processing_step(client, ptypes, params,
237 					   PKCS11_FUNCTION_DECRYPT,
238 					   PKCS11_FUNC_STEP_ONESHOT);
239 		break;
240 	case PKCS11_CMD_ENCRYPT_FINAL:
241 		rc = entry_processing_step(client, ptypes, params,
242 					   PKCS11_FUNCTION_ENCRYPT,
243 					   PKCS11_FUNC_STEP_FINAL);
244 		break;
245 	case PKCS11_CMD_DECRYPT_FINAL:
246 		rc = entry_processing_step(client, ptypes, params,
247 					   PKCS11_FUNCTION_DECRYPT,
248 					   PKCS11_FUNC_STEP_FINAL);
249 		break;
250 	case PKCS11_CMD_SIGN_INIT:
251 		rc = entry_processing_init(client, ptypes, params,
252 					   PKCS11_FUNCTION_SIGN);
253 		break;
254 	case PKCS11_CMD_VERIFY_INIT:
255 		rc = entry_processing_init(client, ptypes, params,
256 					   PKCS11_FUNCTION_VERIFY);
257 		break;
258 	case PKCS11_CMD_SIGN_ONESHOT:
259 		rc = entry_processing_step(client, ptypes, params,
260 					   PKCS11_FUNCTION_SIGN,
261 					   PKCS11_FUNC_STEP_ONESHOT);
262 		break;
263 	case PKCS11_CMD_VERIFY_ONESHOT:
264 		rc = entry_processing_step(client, ptypes, params,
265 					   PKCS11_FUNCTION_VERIFY,
266 					   PKCS11_FUNC_STEP_ONESHOT);
267 		break;
268 	case PKCS11_CMD_SIGN_UPDATE:
269 		rc = entry_processing_step(client, ptypes, params,
270 					   PKCS11_FUNCTION_SIGN,
271 					   PKCS11_FUNC_STEP_UPDATE);
272 		break;
273 	case PKCS11_CMD_VERIFY_UPDATE:
274 		rc = entry_processing_step(client, ptypes, params,
275 					   PKCS11_FUNCTION_VERIFY,
276 					   PKCS11_FUNC_STEP_UPDATE);
277 		break;
278 	case PKCS11_CMD_SIGN_FINAL:
279 		rc = entry_processing_step(client, ptypes, params,
280 					   PKCS11_FUNCTION_SIGN,
281 					   PKCS11_FUNC_STEP_FINAL);
282 		break;
283 	case PKCS11_CMD_VERIFY_FINAL:
284 		rc = entry_processing_step(client, ptypes, params,
285 					   PKCS11_FUNCTION_VERIFY,
286 					   PKCS11_FUNC_STEP_FINAL);
287 		break;
288 	case PKCS11_CMD_GENERATE_KEY:
289 		rc = entry_generate_secret(client, ptypes, params);
290 		break;
291 	case PKCS11_CMD_FIND_OBJECTS_INIT:
292 		rc = entry_find_objects_init(client, ptypes, params);
293 		break;
294 	case PKCS11_CMD_FIND_OBJECTS:
295 		rc = entry_find_objects(client, ptypes, params);
296 		break;
297 	case PKCS11_CMD_FIND_OBJECTS_FINAL:
298 		rc = entry_find_objects_final(client, ptypes, params);
299 		break;
300 	case PKCS11_CMD_GET_ATTRIBUTE_VALUE:
301 		rc = entry_get_attribute_value(client, ptypes, params);
302 		break;
303 	case PKCS11_CMD_GET_OBJECT_SIZE:
304 		rc = entry_get_object_size(client, ptypes, params);
305 		break;
306 	case PKCS11_CMD_SET_ATTRIBUTE_VALUE:
307 		rc = entry_set_attribute_value(client, ptypes, params);
308 		break;
309 	case PKCS11_CMD_COPY_OBJECT:
310 		rc = entry_copy_object(client, ptypes, params);
311 		break;
312 	case PKCS11_CMD_SEED_RANDOM:
313 		rc = entry_ck_seed_random(client, ptypes, params);
314 		break;
315 	case PKCS11_CMD_GENERATE_RANDOM:
316 		rc = entry_ck_generate_random(client, ptypes, params);
317 		break;
318 	case PKCS11_CMD_DERIVE_KEY:
319 		rc = entry_processing_key(client, ptypes, params,
320 					  PKCS11_FUNCTION_DERIVE);
321 		break;
322 	case PKCS11_CMD_RELEASE_ACTIVE_PROCESSING:
323 		rc = entry_release_active_processing(client, ptypes, params);
324 		break;
325 	case PKCS11_CMD_DIGEST_INIT:
326 		rc = entry_processing_init(client, ptypes, params,
327 					   PKCS11_FUNCTION_DIGEST);
328 		break;
329 	case PKCS11_CMD_DIGEST_UPDATE:
330 		rc = entry_processing_step(client, ptypes, params,
331 					   PKCS11_FUNCTION_DIGEST,
332 					   PKCS11_FUNC_STEP_UPDATE);
333 		break;
334 	case PKCS11_CMD_DIGEST_KEY:
335 		rc = entry_processing_step(client, ptypes, params,
336 					   PKCS11_FUNCTION_DIGEST,
337 					   PKCS11_FUNC_STEP_UPDATE_KEY);
338 		break;
339 	case PKCS11_CMD_DIGEST_ONESHOT:
340 		rc = entry_processing_step(client, ptypes, params,
341 					   PKCS11_FUNCTION_DIGEST,
342 					   PKCS11_FUNC_STEP_ONESHOT);
343 		break;
344 	case PKCS11_CMD_DIGEST_FINAL:
345 		rc = entry_processing_step(client, ptypes, params,
346 					   PKCS11_FUNCTION_DIGEST,
347 					   PKCS11_FUNC_STEP_FINAL);
348 		break;
349 	case PKCS11_CMD_GENERATE_KEY_PAIR:
350 		rc = entry_generate_key_pair(client, ptypes, params);
351 		break;
352 	case PKCS11_CMD_WRAP_KEY:
353 		rc = entry_wrap_key(client, ptypes, params);
354 		break;
355 	case PKCS11_CMD_UNWRAP_KEY:
356 		rc = entry_processing_key(client, ptypes, params,
357 					  PKCS11_FUNCTION_UNWRAP);
358 		break;
359 	default:
360 		EMSG("Command %#"PRIx32" is not supported", cmd);
361 		return TEE_ERROR_NOT_SUPPORTED;
362 	}
363 
364 	DMSG("%s rc %#"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc));
365 
366 	TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc));
367 	params[0].memref.size = sizeof(rc);
368 
369 	if (rc == PKCS11_CKR_BUFFER_TOO_SMALL)
370 		return TEE_ERROR_SHORT_BUFFER;
371 	else
372 		return TEE_SUCCESS;
373 }
374