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